Closed practicalswift closed 9 years ago
:thumbsup: for Alt. 4! Heres another idea: Alternative 5:
seq(100) | (x) -> {
if x % 15 == 0 {
"FizzBuzz"
}
...
} | STDOUT
I agree, I think it's a lot more clear without |x|
. I think I like alternatives 2, 4, and 5 the most so far.
:+1: for Alternatives 2 & 5
I vote 1 & 3
On Mon, Dec 15, 2014 at 4:34 PM, Hugh Francis notifications@github.com wrote:
[image: :+1:] for Alternatives 2 & 5
— Reply to this email directly or view it on GitHub https://github.com/matz/streem/issues/25#issuecomment-67079436.
I don't understand the { |x| ... } syntax. Should we understand this to be an anonymous (stream-oriented) function? If so, the syntax for function definition, anonymous function definition, and this example should be harmonized.
3 is the most ruby-like among the alternatives. I like it.
I feel same way, and agree to change. But I am afraid that alternatives in OP cause shift/reduce conflict. I am thinking of ->x{...}
as function objects/blocks.
FYI, op_rasgn
is not mandatory. we can remove it.
If op_rasgn
was removed, how would you use variables? (I don't think you can have a programming language without variables.)
you can assign using =
, e.g. s = socket.accept()
, instead of socket.accept() -> s
.
@acangiano why are we trying to be like Ruby? Sure, Matz designed ruby, but that doesn't mean everything that has anything to do with him should look like Ruby. Also, I am in favor of keeping the op_rasgn
for assignments, as that is in keeping with the stream-oriented idea. So how about another alternative?
Alt. 6:
seq(100) | (x) => {
if x % 15 == 0 {
"FizzBuzz"
}
...
} | STDOUT
That seems still in keeping with most other languages, (including CoffeeScript and ES6), and wouldn't lead to any shift/reduce conflicts. Also, I do thing that #26 would be something to think about as far as shorthand for transforming and filtering streams.
What about simplifying the syntax further and introducing shorthand argument names $0
, $1
, $2
, etc:
Alternative 7.
seq(100) | {
if $0 % 15 == 0 {
"FizzBuzz"
}
...
} | STDOUT
foo | {
zip($0, $1)
} | STDOUT
Reasoning:
$0
, $1
, etc should be obvious from the preceding command/function (seq(100)
in this case).In cases where argument names are needed for readability the syntax would be a slightly modified version of alternative 3 above to avoid the shift/reduce conflict that @matz mentioned in his comment:
Alternative 8.
seq(100) | (x) {
if x % 15 == 0 {
"FizzBuzz"
}
...
} | STDOUT
foo | (arg1, arg2) {
zip(arg1, arg2)
} | STDOUT
Reasoning:
(arg1, arg2) { … }
can be read as a shorthand for the familiar function_name(arg1, arg2) { … }
.So I suggest to allow for BOTH alternative #7 and alternative #8 depending on if named arguments are required or not :-)
I like the haskell-like lambda syntax:
seq 1 100 | \x -> length x | print
seq 1 100 | lines | map (\x -> length x) | fold sum | print
Of course if currying is good supported, \x -> length x
can be simplified into a sole length
. Pretty neat I consider this syntax :)
If a block is wanted, we could take
seq 1 100 | \x -> {
do something...
} | print
Probably alternative #9? Actually it's just similar to alternative #5.
I don‘t like (arg) to be outside of the {…}. because if I want to write some codes to calculate 1/1+1/2+…+1/10 and print sum at last like this:
seq(10) | (x) {
sum += 1/(x)
{
print sum
}
}
It looks like a num divided by a function! At last,I give a alternative too:
seq(100) | { (x => f b)
if x % 3 == 0 {
f = x
}
else if x % 5 == 0 {
b = x
}
} | { (x y)
printf("total fizz:%d\n", count(x))
printf("total buzz:%d\n", count(y))
}
@Krysl please edit your comment to mark your code as a code block to make it more readable
I like alternative 3
:+1: alternative 5
seq(100) | #(x) { | x % 3 == 0 --> f = x | x % 5 == 0 --> b = x } | print
seq(100) | #{
| Odd --> f = x
| Even --> b = x
} | print
Perhaps the closure parameter can be omitted when there is only one argument
Alternative 7 can be implemented alongside any other block parameter syntax for when no block parameters are explicitly declared, kind of like Clojure's compact lambda syntax. It would be nice for one-liners. The downside is that it makes a class of typos hard to detect, e.g., if you type $1
instead of $0
on accident how can the interpreter tell if you meant it? For this reason you'd want a more explicit syntax to be there as well for longer scripts.
:+1: Alternative 7 & 5 together. Like in Clojure.
I liked @tbodt's idea of creating a table of votes in #24, so I'll add one for the alternatives here:
Alternative | Votes | Syntax | Note |
---|---|---|---|
1 | 2 | { |x| … } |
current syntax |
2 | 3 | { (x) -> … } |
|
3 | 4 | { (x) … } |
|
4 | 2 | { x -> … } |
|
5 | 5 | (x) -> { … } |
|
6 | 1 | (x) => { … } |
|
7 | 2 | { } |
parameters are $0 , $1 , $2 , etc. |
8 | 1 | (x) { … } |
|
9 | 1 | \x -> { … } |
Last updated: this comment.
Sorry if I excluded anyone, I tried to only include votes that were more explicit, and only alternatives that were numbered to make things simpler.
By the way, in the future, it might be easier to use some sort of wiki and/or poll site to organize alternative ideas. http://poll.gitrun.com seems interesting.
I like alternative 3
I am afraid alternatives 2,3,5,6,8 will cause shift-reduce conflict. I like alternative 10, which is
-> x { ... }
similar to Ruby's lambda.
That might be confusing if you want to assign a lambda to a variable. Alt. 6, 8, and 4 are the least likely to cause conflicts.
@matz Let's say you decide to go with alternative 10, would you consider also having alternative 7 available? As I see it those should not be mutually exclusive, and I think alternative 7 is proper for quick Streem scripts (c.f. shell scripts) where the number of parameters are few and naming them feels overkill.
Just as the meaning |
is immediately obvious to everyone with shell experience (which should be more or less all programmers), I think the numbered arguments ($0
, $1
, etc.) in alternative 7 has the same intuitive appeal for anyone with shell scripting experience :-)
My suggestion:
From a pure standpoint of appearance, I don't like Ruby's lambda syntax at all. Most modern languages go with something like (x) -> {}
, and every time I return to write codes in Ruby, the very syntax feels like pretty weird.
So big :-1: 10, but :+1: 5 (6 is also okay).
Or, once again, the parser of Streem is supposed to be so complicated and chaotic that you can't implement a standard syntax?
@shunsukeaida I don't know how other language works (yet), but when the parser see
(a)->{...}
it's quite difficult for the parser to distinguish (a)->
(beginning of a function object) and (a)
(a variable surrounded by parentheses), without shift-reduce conflicts. Other parsers may do precedence tricks, or ignore conflicts.
Alt. 6 is very similar to Alt. 5. Maybe that's what we should go with.
Anyone here knows Microsoft Powershell (http://technet.microsoft.com/en-us/library/hh847902.aspx - "about_Pipelines")? Streem immediately reminds me of it.
In Powershell, objects sent thru the pipeline get assigned to '$_' by default, which would be like option 7, but a single parameter (not sure if you can have more than 1 object sent thru at a time), which is good for quick scripting/oneliners, but when declaring functions you can assign them to named variables (in a more bureaucratic way than most *nixers are probably used to).
Anyway, I personally don't fancy the little arrows, typing '()' or '||' requires less finger traveling.
So I'd like 7 (by default) plus 3.
Also I'd like to note this looks to me like a language/shell for sysadmins, not necessarily full blown programmers. :]
{ <a, b> ... }
or <a, b> { ... }
cannot be confused with pipes.
The similarity between the flow operator (
|
) and the block parameter syntax (|x|
) will probably be a source of some confusion since|x|
can be misinterpreted as "a pipe through x".The problem is not the flow operator (
|
). On the contrary – using the pipe as the flow operator conveys the meaning very intuitively for everyone who has ever used a shell, so let's keep that very good choice.Instead I suggest switching from
|x|
to say(x) ->
,(x)
orx ->
to denote block parameters.The
(…) ->
alternative is implemented here: https://github.com/practicalswift/streem/commit/193fa8413d14dce03d609ec597006a40ca678ec1Reasoning:
(parameter1, parameter2, parameter3, …)
should be familiar to most programmers.->
is used for assignment in the Streem syntax (seeop_rasgn
inlex.l
).Summary of discussed alternatives:
Alternative 1 (current syntax).
Alternative 2 (implemented here: https://github.com/practicalswift/streem/commit/193fa8413d14dce03d609ec597006a40ca678ec1).
Alternative 3.
Alternative 4.