Closed stugol closed 9 years ago
My opinion:
Cool, but not really needed; you can just do:
puts fn fn fn 1
which I find more readable.
Also not really needed; Crystal already has map:
puts [1,2,3].map(fn).map(fn)
puts [1,2,3].map &.to_s
3) MyObject.new.tap(&.somefunction).tap(&.someotherfunction)
?
you can use try, for !
you can use not_nil!
(no need for new syntax).:
conflicts with foo ? bar : baz
.
, which is shorter and more readable in my opinion.end
makes it hard to implement the macro syntax that we have right now, where basically indentation and whitespace don't matter. Then if you have a templating language for, for example, embedding HTML, you'll wish you had those end
again, or you'll have to put them anyway and remove them later.I don't like the tap syntax, it's too noisy. And you can't concatenate free function calls with .
.
And the problem with puts fn fn fn 1
is that you must read it in reverse order. It's less intuitive to read.
I put it to you that Ruby, and hence Crystal, are functional languages. Pretty much everything is an expression.
Incidentally, I've never understood language designers' dislike of new syntax. I love new syntax. When Rust dropped the ^
token in favour of Box<T>
, I really felt it was a step back. I would much prefer to write a |> b |> c
instead of a.map(&.b).map(&.c)
, and int ^a
instead of Box<int> a = gcnew Box<int>()
. I mean, wouldn't you?
Aside from Swift, pretty much no language in common use supports user-defined operators. If Crystal did, these questions would all be pretty much moot. Any chance of that?
(Although of course, Rust is a pointless language. It supports neither function overloading nor optional arguments, so what good is it?)
@stugol New syntax is fine...until there is too much syntax, at which point learning the language and reading others code becomes a pain in the neck.
Jeeez, waaaay too many topics for a single issue. Seriously, you're harming the chances of properly discussing anything you want this way.
Anyway, most of what and why I disagree with has already been said. I also favour composing language constructs over adding syntax, since it decreases the entry barrier and makes the language more powerful by extending it with new constructs that don't feel alien in library code.
For 1 you can do a little bit of AST manipulation, like the maybe
macro I wrote recently: http://carc.in/#/r/8uc
And &.
allows chaining, you can do MyObject.new.tap &.foo.bar.baz
(no need for the return in most cases, less syntax \o/) and [100, 200, 300].map &.to_s(36).upcase
and so on.
I like this issue - because so many of the points are similar or the same as my own wishes :)
?
. The alternative &.
would clash with other constructs - the mysterious one I don't quite have grasped the syntax for yet (auto block &.* up til next white space) - might be a conflict of intent. Though personally I'm leaning more towards the ?, and ditching it as an identifer char - but the great majority seems to feel the opposite, so it probably should be untouched.::
vs. :
question regarding type annotation, #758. I feel strongly that all type notation should be done with one single colon - not two. That would clash with this notation. But that already clashes with ternary, as @asterite mentioned (which I'd like to see prefixed with an if
to disambiguate [see #937]). However, I find this quite neat: some_array.1 = 47
- which gives a visual clue to mathematical subscript. I like that. For hashes (or rather non-numerical index keys), perhaps it could be some_hash#some_key
? Might be problematic with the hash in lexing (here strong spacing [none] could be a part of the deal)? Haven't studied. I would really enjoy this feature in some configuration.1.fn.fn.fn
(provided accesses on methods still means they're called). This would be more uniform with Crystal, while still using free functions, and is both terser and cleaner (as mentioned, I've used both alot, so this opinion isn't prior-usage-bias).fn arg1, arg2
) - the space after a callable means juxtaposition syntax call. So it obviously has previous use, and obviously is fully "graspable". But - function/method calls are so common place, it becomes second nature to look out for it. In this case the use would be more sporadic, thus there would be a much greater risk of misinterpreting the intent ("is it a bug?"). Reading the code, I would find puts (2 * 4).increment
to be much clearer in displaying intent. Some redundancy is important to avoid confusion in what the code communicates to a human.end
(which I've simulated in some sig. ind. langs by defining constant end
as null - it's a visual que - but doesn't give helpful compilation checks).
The arguments against, macros, I don't really get; any code blocks / tokens passed to macro should be normalized indent wise to where they're pasted - no??
I would be super happy if this was available through a parsing directive at top of source if it won't cut it as default!!! I would love to help out implementing it too if it can be of help.Notes:
To chain free function calls (the ..
notation) would require UFCS - something I'd really like to see in Crystal - since it can unify style in code much more (using method style for free functions for better clarity in many cases). With reopen-able classes that Crystal has, the one argument against them is already moot imo, so they should bring just benefits (ok, ok, more work on the compiler - granted).
My 2 mBTC
I'll close this issue. I think we are in a point where we'd like to avoid adding syntax for things that can be already done, if they don't provide a huge benefit. And some of the things are answered in the FAQ or are discussed in other issues.
And please, next time try to open an issue for each thing you want to discuss. Thanks!
Oh, such an old thread :sweat_smile:
Unnecessary whitespace lowers operator precedence. This would tidy up certain expressions that currently involve ugly parentheses.
struct Int32; def increment; self+1; end; end
puts 2 * 4.increment # => 10
puts 2 * 4 .increment # => 10
:tada:
But he wants 9 for the second example :-P (which of course will never happen)
Here are a few features that I feel Ruby - and therefore Crystal - could benefit from. Please consider adding them to the language.
Granted, they're mostly syntactic sugar, but I like plenty of sugar on my languages. Otherwise I'd code in assembly language.
1) Null-propagating operator, as seen at https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/OptionalChaining.html. Example:
a = myobject?.method1?.method2
if any of these things are (or return) nil, sets a to nil and doesn't crash. I suggest&.
for this purpose, as?
already has a meaning in Ruby/Crystal.2) Terse hash and array access:
3) Cascade operator. Allows calling methods of an object without assigning it to a temporary, and without affecting its eventual lexical value. Might need to pick a different operator, as
..
already has a meaning.Equivalent to:
4) Pipe operator. Nicer syntax for calling free functions in a chain. Useful to avoid nested calls. Accepts local free functions, proc objects and blocks.
5) Pipelining operator. Like the pipe operator, but works on collections. Accepts local free functions, proc objects and blocks. Also accepts methods of the items.
6) Unnecessary whitespace lowers operator precedence. This would tidy up certain expressions that currently involve ugly parentheses.
7) Indent-based nesting, like python, with automatic
end
keyword. Maybe require a flag at the top of the code to enable this, to avoid breaking existing code.