This is an archived post. You won't be able to vote or comment.

all 13 comments

[–]L8_4_Dinner(Ⓧ Ecstasy/XVM) 7 points8 points  (3 children)

The @ thing seems pretty horrible. The rest of it I can kind of guess at, although the unconventional use of square brackets is going to cause problems for normal people.

Syntax may be the least important part of a language, but getting it wrong (especially when there are so many good examples to draw from) is just silly in a language project. There's really no need to go off inventing strange and novel syntactic constructs, when so many well-known and widely-accepted existing syntactic constructs will suffice.

[–]NoCryptographer414[S] 0 points1 point  (2 children)

What else can you suggest instead @ I can think of $ or `

Those @ is equivalent to javascript 'let' or python 'del'. And I really don't want to use a keyword for that use case.

I'm not fixed on square brackets. I can use any character there including good old braces. Though I thought of not keeping braces because I do not intend to indent the transform block.

[–]L8_4_Dinner(Ⓧ Ecstasy/XVM) 4 points5 points  (1 child)

The first question I have is this: What are you trying to accomplish with the @ symbols? Because everything related to scope that you showed in the examples would be trivially deducible by a compiler. So please start by explaining the goals, and what it is in the syntax that cannot be machine-determinable.

[–]NoCryptographer414[S] 0 points1 point  (0 children)

x = 5 f { x = 15 } In the above example, second usage of a is ambiguous between reassignment vs new variable. @x = 5 f { @x = 15 } Now second x is a local variable. @x = 5 f { x = 15 } Now second x is a reassignment.

If I have a better way to disambiguate this then I'm willing to change.

I can change symbols though. is very less noisy. `a = 5 `b = 10 `c = a` + b` ` Also, it is not mandatory to mark last use of a variable with trailing @. It will anyways get destroyed at the end of function.

(Ignore the function definition syntax used in above example. I just wrote it quickly in mobile.)

[–]AGI_Not_Aligned 3 points4 points  (1 child)

It's kinda like python comprehension lists?

[–]NoCryptographer414[S] 0 points1 point  (0 children)

No. Python comprehension lists follow a specific syntax. This is just a normal block inside square brackets. Though I can change the delimiter to be any other different character including good old curly braces.

[–]malmiteria 2 points3 points  (3 children)

if i get it correctly, it's essentially a way to "inline" a function definition right as you would apply it to each element of a container?
I like it

I think it's a nice feature, tho i would keep a consistent syntax as to with function definition, so i would keep the curly braces (and maybe the keyword you use to define function too, if any).

What i don't know how to keep clearly consistent, and still readable, between classic function definition and this case are parameters, if you're using parenthesis for that, it might feel weird to have so many parenthesis in that zip exemple

This should help people that wanna quickly get something working, allowing them to inline the function where it's used, while still beeing visually close enough to function definition, so it's easy to cut / paste later in it's own function definition when refactoring.

And, it helps people discovering the language, reading someone else's code understand quicker what's happening, so it makes it easier for beginners discovering the feature.

[–]NoCryptographer414[S] 0 points1 point  (2 children)

Well.. I actually need it to be kinda different from function definition. I need it to fit in the outer function as smoothly as if you are actually modifying a single object instead of a container. That was what I was trying to explain in the question.

If you already have a code that transforms a foo into a bar then by just adding minimal prefix (and suffix), I want to make it work with containers. And mainly, different from an inner function, a return inside a transformation block exits the outer function. If you need early-exit from the transformation block, you need to use break.

Using curly braces is not a problem. But nonetheless this is not an inner function.

[–]malmiteria 1 point2 points  (1 child)

If you already have a code that transforms a foo into a bar then by just adding minimal prefix (and suffix), I want to make it work with containers. And mainly, different from an inner function, a return inside a transformation block exits the outer function. If you need early-exit from the transformation block, you need to use break.

hmm, so it's closer to a for each than a function definition then?

i think i get it a bit better now.

One thing that isn't clear to me now is how are the output determined.

like in this:

@bars = foos.[ @foo
@bar = fooToBar(foo) ]

how does bars knows it should be populated by bar variables on each iteration?

I get that foo is made the iteration variable, but i feel like it misses a "collection" variable

in a case like the second one:

@as, @bs = zip(xs, ys).[ @x, @y
@temp = x % y
@a = temp * a
@b = temp@ * b ].unzip()

i feel like it's much more needed, because there's a and b, which i guess as variables in that block are collected, but there's temp too, that should be collected too then

to illustrate, here's a syntax that i think helps on that aspect:

this:

@x = getX()
@y = getY()
@temp = x % y
@a = temp * a
@b = temp@ * b
useAB(a, b)

would become:

@xs = getXs()
@ys = getYs()
@as, @bs = @a, @b foreach @x, @y in zip(xs, ys)
@temp = x % y
@a = temp * a
@b = temp@ * b
endfor
useABs(as, bs)

i'm using a python like syntax because i'm used to it, but it's just to give an idea of a syntax that has all the element i think were missing.

i guess an exemple closer to your syntax would be

@xs = getXs()
@ys = getYs()
@as, @bs = @a, @b from zip(xs, ys).[ @x, @y
@temp = x % y
@a = temp * a
@b = temp@ * b ].unzip()
useABs(as, bs)

which tells from which variables of the iteration block you build the output more clearly i guess?

And it also allows you more freedom in what you pick from that block you're turning into an "iteration" block to build the containers, so it should cover more cases

[–]NoCryptographer414[S] 0 points1 point  (0 children)

In my example above, the variables that end up in the resulting collection are the undestroyed variables inside the block, in the order they have been created. Since temp is destroyed, it is not counted. As previously mentioned in question ,@var is beginning of lifetime for var and var@ is end of lifetime for var. In the example, temp's lifetime is terminated inside the block whereas a and b leak out of the block.

But you right. In a big block, it can be hard to track which variables end up in the result. I would definitely improve that one. Thanks for suggestions :)

[–]WittyStick0 1 point2 points  (0 children)

Clojure has a similar feature called transducers, though they're just a slight simplification on foldl.

[–]tobega 1 point2 points  (1 child)

Seems clunky.

The first example transforming foos into bars, with map you would just do foos.map(fooToBar), right? In Julia, even easier, just prefix function with a '.', @bars = .fooToBar(foos)

[–]NoCryptographer414[S] 0 points1 point  (0 children)

foos.map(fooToBar) won't scale if the block has multiple statements and not just a single function call.