6 ms·
Ask HN: Your favorite syntactic sugar from any language?
Most programming languages I've encountered, no matter how otherwise unappealing, have at least one syntactic feature that makes them really pleasurable for at least some type of task.
Some things I miss when I don't have them are:
* "=~" for regex matching (as in Perl and Ruby)
* "{foo:['bar','baz']}" for quick data structures (as in JavaScript)
* "for f in *; do echo $f; done" for looping over a 'glob' of files (as in Bash)
What's your favorite bit of sugar?
- AnimalMuppet 8y agoThe defaults in Perl, especially the default variable. (For those not familiar: $_ is the default variable in Perl. Many operations use this variable if you don't specify one. You can use $_ like "it" in English: "Read in a line of input. If it ends in a newline..." In most languages, you would have to deal with "Read it into where?" and "If what ends in a newline?" But in Perl, if you don't specify where to read the line to, it goes into $_, and if you don't specify what you want to see if it ends in a newline, it checks $_, and so on...)
- ramses0 8y agoThis is worth a bit of explanation, see this link and the code duplicated below: https://perlmaven.com/the-default-variable-of-perl https://perlmaven.com/the-default-variable-of-perl I agree with most everything the author says, along with the idea that you shouldn't use it that often. ---------- use strict; use warnings; use v5.10; while ($_ = <STDIN>) { chomp $_; if ($_ =~ /MATCH/) { say $_; } } ---------- use strict; use warnings; use v5.10; while (<STDIN>) { chomp; if (/MATCH/) { say; } }
- deleted 8y ago[deleted]
- ioddly 8y agoScheme's expression comments are really quite handy, but only possible to implement in languages where everything is an expression. For those not familiar, you can have the reader just discard an expression, so like (list 1 #;2 3) becomes (list 1 3), but you can handily comment out a giant function call or if expression or something while you work on it. Scheme's nestable multiline comments are also nice. I'm not sure which language was first, but I think more languages are getting them now (Kotlin has them IIRC).
- EvenThisAcronym 8y agoD has also had them since the early 2000s.
- rehemiau 8y agoPipeline operator ( |> ) in functional programming languages (Elixir, F#, Elm)
- charlieflowers 8y agopossibly async/await
- fvdessen 8y agoI really like python's array slices, a[5:] b[2:3], and list comprehensions, [x * 2 for x in array if x > 0]
- artemisyna 8y agoArray slices make array/string-parsing coding interviews so much nicer. @.@
- lotu 8y agoSo much so, I wish more languages would adopt it.
- Pete_D 8y agoI love Python comprehensions. I want to dislike Python - significant whitespace, weak lambdas, other trivial complaints - but the comprehensions are so nice, especially combined with yield and the iteration protocol, that it's usually the first language I turn to. There's syntax for sets, dicts, and generators too: >>> { char.upper() for char in "hello" } set(['H', 'E', 'L', 'O']) >>> { char: ord(char) for char in "world" } {'d': 100, 'r': 114, 'o': 111, 'w': 119, 'l': 108} >>> (char for char in "foobar").next() 'f'
- Tijdreiziger 8y agoWhat I really dislike about comprehensions is that the for syntax comes at the _end_. They would be much easier to parse if it came at the beginning.
- kjeetgill 8y agoI used to feel that way too. When you write out nested for loops the work is at the other end! For what it's worth, it is meant to resemble mathematical set builder notation. I think that familiarity turned me around on it (pun intended). From that perspective it feels more natural. [0]:https://en.m.wikipedia.org/wiki/Set-builder_notation https://en.m.wikipedia.org/wiki/Set-builder_notation
- artemisyna 8y agoHaskell has way too much syntactic sugar some of the time, but I really appreciate its anonymous function syntax. If I need a quick-and-dirty map over a list of something, a (\x -> x + 1) a is much nicer than a std::for_each(a.start(), a.end(), [](float x) { return x + 1; } // end of lambda expression ) or whatnot that I have to do in C++.
- stochastic_monk 8y agoYou're really looking for `std::transform`. On the other hand, for(auto it(a.start()); it < a.end(); ++(*it++)); and for(auto &el: a) ++el; aren't terribly verbose.
- nicoburns 8y agoJavaScript lets you do: a.map(x => x + 1) which is pretty nice. And Rust lets you do: a.map(|x| x + 1) C++ syntax is just awful, and especially for functional stuff.
- himom 8y agoSwift closure syntax, at least in <= 2.0, made for awkward API calls, since it wasn’t clear whether inline or after closures were used. In Ruby, a.map(&:succ)
- steveklabnik 8y agoIf you have a named function, rust lets you do a.map(succ) as well, since functions can be used where closures can, as long as the types work.
- jeffmcmahan 8y agoSame in JS
- erik_seaberg 8y agoI'm still surprised Haskell is the only language I've ever seen in which the "add 1 to your argument" function is simply (+ 1)
- snappyTertle 8y agoDestructuring in almost any functional language and ES6 JS.
- deleted 8y ago[deleted]
- Pete_D 8y agoCommon Lisp's LOOP macro is a fearsome beast. http://www.ai.sri.com/~pkarp/loop.html http://www.ai.sri.com/~pkarp/loop.html http://www.lispworks.com/documentation/HyperSpec/Body/m_loop.htm http://www.lispworks.com/documentation/HyperSpec/Body/m_loop...
- ralston 8y agoPython 3.5+ >>> first = {"a": 1} >>> second = {"b": 2} >>> merged = {**x, **y} >>> print(merged) {"a": 1, "b": 2}
- ezekg 8y agoPython/Ruby's kwargs, JavaScript's destructuring syntax, Python list comprehensions, Ruby's array push << method, ranges, and literal array expressions
- farleykr 8y agoI just discovered being able to use Python to convert a number to a different base: >>> int(‘x’, y) ...where x is the string/number you want to convert and y is the base. I haven’t found a practical use case but it’s been a lot of fun to play with.
- jwilk 8y agoIt's not a syntactic feature, so it can't be syntactic sugar. Also, it's available in many (most?) other languages: C (strtol), C++ (std::stoi), JavaScript (parseInt), PHP (intval), ...
- tu7001 8y agoList comprehension - Python, Haskell.
- LordHeini 8y agoBeying somewhat of a functinal fanboy i really like Scalas (and oder functinal languages) point free style. Instead of: listOfThings.foreach(x => println(x)) You can just type listOfThings foreach println Type inference is also great. Scala in general has lots and lots of syntactic sugar, which is kind of the point of Scala. Honroable mention: Rubys &. operator instead of y = x.nil? ? nil : x.foo y = x&.foo Or just use a language which has some sort of null savety like Option types.
- kendallpark 8y agoRuby inline conditionals. They read like English. Short and sweet. if condition? return end if !i_probably_shouldnt? do_something end Becomes: return if condition? do_something unless i_probably_shouldnt?
- deleted 8y ago[deleted]
- derefr 8y agoWhen writing one-off Ruby scripts, I especially like using the single-line unless with Kernel.fail: fail "bad arg" unless dir = ARGV.shift (If you could figure out a way to also stuff that line with a transformation to a Pathname for not-nil results, I'd be in heaven.)
- jitl 8y agoTakes a bit of setup to monkey-patch String, but: class String def to_pn Pathname.new(self) end end fail "bad arg" unless dir = ARGV.shift&.to_pn
- nunez 8y agoRuby’s question marks for Boolean functions and exclamation points for mutating ones. I didn’t get t at first, but once I did, I was in love. Perfect for readabiiity.
- city41 8y agoclojure has this as well and I really like it. Although `!` in clojure usually signifies the function has side effects.
- DonaldPShimoda 8y agoDo you mean like functions named `is_empty?` and `set_value!`? If I've been told right, this comes from Scheme. I first experienced it in Racket, and I absolutely love it. It's seriously one of the greatest conventions.
- domlebo70 8y agoDo notation in Haskell, Scala etc. Nothing else comes close
- tylerhou 8y agoYou don't need do notation in an imperative language, though.
- piinbinary 8y agoDo notation can act like an imperative language, but it can also do a lot of things imperative languages can't (e.g. the list monad, or the continuation monad).
- imh 8y agoYou don't need the IO or state monads in other languages, but that's not the only useful monad. Applicative functors with their own do notation are pretty cool too.
- city41 8y agoI miss CoffeeScript's existential operator now that all my projects are standard ES6. https://coderwall.com/p/jwzppw/the-existential-operator-in-coffeescript https://coderwall.com/p/jwzppw/the-existential-operator-in-c...
- jamesisaac 8y agoThis is currently a stage 1 proposal for the core language: https://github.com/tc39/proposal-optional-chaining https://github.com/tc39/proposal-optional-chaining Depending on your stack it might be possible to make use of it already, e.g. Babel has a transpilation plugin, and Flow supports it for static type-checking.
- hprotagonist 8y agoI really like C#'s => operator, especially in the context of expression-body members. public override string ToString() => $"{fname} {lname}".Trim(); I am overjoyed with newer python's f-strings. foo = 5 bar = 4.5005 print(f'foo is {foo} and the first bit of bar is {bar:0.2f}') I really like python's * and * unpacking, and especially that you can do it in the middle with throwaways: first, *_, last = function_that_returns_ten_things() or for building kwarg-only classes from dicts: foo = {'x':5,'y':6} bar = Point(**foo)
- laogai 8y agoRuby's & operator. At first I hated it because of how incomprehensible it was to someone coming from seemingly every other language, but I've started to use it more and more and wishing it existed in other languages. It's especially useful for when the variable access is many characters. e.g. `if hackerNews.frontPage.votingCircleExists:` with nil checks is `if hackerNews && hackerNews.frontPage && hackerNews.frontPage.votingCircleExists` and with & operator is: `if hackerNews&.frontPage&.votingCircleExists`.
- kjeetgill 8y agoThis is exactly how Python's 'and' and 'or' work too. The first time I saw it I was baffled. It took me a good while to fully wrap my head around it. I grew to love it. Edit: I was mistaken, it's a little different. This is more like groovys safe navigation ?.
- deleted 8y ago[deleted]
- christophilus 8y agoAgreed. Null conditional operators are definitely handy in languages that have nulls. C# has this in the form of ?.
- kjeetgill 8y agoThis is there piece of C# I'm most envious of missing out on in Java.
- kjeetgill 8y agoI love love love almost everything about Python's syntax. Slices that support negative indexes. List and dictionary comprehensions are amazing: { (X,Y): X2 + Y for X in range(10) for Y in someiter if Y > 5} I love that they become generators when you use () instead of []. Pure genius. Generators from a function containing yield or yield from equally beautiful. % for string interpolation was so good they had to bring it back. Tripple quotes using """ and ''' are hard to beat. Using func(list) to unpack a list into a functions arguments. Or func(dict) to unpack a map by name. Using args and kwargs to implimentaions variadic functions. I love indentation based code blocks. The way 'and' and 'or' can return values is so much better than a ?: terinary. I think I dumped a third of the Python spec there. I could use a multi-line lambda but it's not a huge omission. Pipelines like bash | pipe or F# |> would be welcome. go's select statement is also subtle but smart. Doing multiple waits in one thread is tricky to impossible in most any other language. Built in regex like perl is always nice when you have it. I'm sure I missed something gushing over Python, but tapping this out over the phone if already killing my thumb. Java desperately needs groovys's safe navigation operator a?.getB()?.getC(). It's like a normal method call but returns null if the receiver is null instead of throwing an NPE.
- DonaldPShimoda 8y agoI love Python too (a lot), but I disagree with some of these. > I love that they become generators when you use () instead of []. I kind of like this, and I kind of hate it. My second-favorite language is Haskell, where everything is lazy, so to me it almost seems like everything should be generators anyway (except when a value is expected). > % for string interpolation was so good they had to bring it back. I hate % for string interpolation. It's ugly. Why do my variables need "variables" in the strings? It's indirect interpolation. I far prefer f-format strings, because `print(f"Correct: {correct}/{total}")` reads much better. > Tripple quotes using """ and ''' are hard to beat. Unconvinced. I feel like the syntax for multiline strings could be a bit simplified. Also, it's a pain to combine multiline strings with indentation. I don't want all the extra whitespace at the fronts of the lines, but I also don't want to process the text immediately afterwards... sigh. But I totally agree with the other points. Overall, the syntactic sugar is phenomenal! Just these points I disagree about.
- jwilk 8y agoSyntactic sugar is not another name for "really cool syntax". They are non-essential constructs, which could be removed without much effect on the language, except for readability. "=~" in Perl and globbing in shell are not syntactic sugar. They are fundamental parts of the languages.
- garmaine 8y agoTo follow on from this, "syntactic sugar" is a permitted short-hand that can be losslessly transformed into another, often more verbose construction. This is why it must, definitionally, add no new features. For example, list comprehensions in Python: `[x^2 for x in L if x < 10]` is EXACTLY the same as `map(lambda x:x^2, filter(lambda x: x<10, L))`. The list comprehension is just easier on the eyes.
- DonaldPShimoda 8y ago> `[x^2 for x in l if x < 10]` is EXACTLY the same as `map(lambda x:x^2, filter(lambda x: x<10, l))` Except the former resolves to an actual list value, whereas the latter is a generator. (You would've been right if you'd used the generator syntax () instead of the list comprehension syntax []. Just thought I'd point it out since this whole thread is about syntax.)
- asdfologist 8y agoThat's true for only python 3.
- DonaldPShimoda 8y agoThe other commenter didn't specify, which led me to believe it was a (simple) mistake on their part. You're not wrong, but it seems to me that dragging out this phase of "Well Python 2 had X but Python 3 has Y" will not help people move to all being on 3. (And, with some exceptions, everyone should really be moving to 3.)
- Sohcahtoa82 8y ago
- aqme28 8y agoRuby's ||= `a ||= b` sets a to b, unless a is already defined.
- emorning2 8y agoasync/await I see async/await as the only way to write asynchronous code that's readable
- aphextron 8y agorange() in Python [foo, bar, ...baz] ES6 Destructuring
- amthewiz 8y agoRuby's optional parenthesis for function calls. Makes beautiful DSLs like RSpec - describe UsersController do before do allow(controller).to receive(:current_user).and_return(nil) end describe "GET #new" do subject { get :new } it "returns success" do expect(subject).to be_success end end end
- kjeetgill 8y agoBut I love the brace free dsl. It's pretty. How van you tell how many tokens it takes? Describe or subject take? It's a bit hard to parse, but I don't know Ruby. Coming from Python the end end end hurts though. Why not just use braces then?
- geoelkh 8y agoA lot of things in Ruby like if !disabled //instead of unless disable
- BigToach 8y agoDecorators in any language.
- jedberg 8y agoPython list comprehensions. They could be written as multiline loops, that are definitely more readable, but it's just so nice to whip out a list comprehension sometimes: print([int((((1 + 5**0.5) / 2)**n - ((1 - 5**0.5) / 2)**n) / 5**0.5) for n in range(1, 21)])
- imh 8y agoPython 3's string formatting is pretty useful.
- frfl 8y agoSorry, this comment will not really benefit the matter at hand, but I'd like to share a relevant quote I quite enjoyed when I first read it > Syntactic sugar causes cancer of the semicolon. - Alan Perlis
- pdgonzalez872 8y agoThe pipe operator in Elixir.
- himom 8y agoTechnically, any Turing-complete language can be mapped to any other Turing complete language, so it’s possible to have non-trivial syntatic sugar do anything. (Use brainfuck as IR, lol.) >:) But yeah, SS is more like: ++x; // x = x + 1 Nifty syntax &:foo Ruby method name to callable syntax foo&.bar Ruby check nil before calling bar foo?.bar Swift optional presence check if(x = foo!.bar!) { x.something() } foo ?? bar Swift nil-coalescing foo || bar Ruby nil-coalescing <<1,4,8,45>> Erlang bit syntax (binary literals), with typing and endianess 5b432140 Erlang arbitrary base literals List comprehensions Erlang, Python, Binary comprehensions in Erlang 2> Pixels = <<213,45,132,64,76,32,76,0,0,234,32,15>>. <<213,45,132,64,76,32,76,0,0,234,32,15>> 3> RGB = [ {R,G,B} || <<R:8,G:8,B:8>> <= Pixels ]. [{213,45,132},{64,76,32},{76,0,0},{234,32,15}] -- from LearnYouSomeErlang Show anon fn’s in many languages using utf8 λ. Swift property lifecycle callbacks
- christophilus 8y agoFor me, it's Clojure's threading macros. They're like the `|>` operator on steroids. Also from Clojure, the ability to use maps and keywords as functions in a lot of cases, such as: `(map :hello [{:hello "world"}]) ; ["world"]` and `({:hello "world"} :hello) ; "world"` It comes in really handy more often than I would have thought.
- RhysU 8y agoHaskell dollar operator ($). Last I checked, it fits into the Python grammar if anyone feels PEPpy.
- timwis 8y agoJavaScript's async/await is our reward for suffering promises. Not perfect, but makes the language a lot more approachable IMO.
- AndrewDucker 8y agoThe one that's saved me the most time is probably "foreach" as a way of accessing enumerables in c#. Simple, readable, and easy.
- singularity2001 8y agoI love kotlin lambdas with «it»: list.filter{ it > 3 }.map{ it + 1 } compare that to shitty Java or C++ . Love js map construction by name: fun="..."; map={fun}; map.fun == "..." Nice lambdas and properties are the things I miss most in python, especially python3, where you have to call list(map(...)) all the time (generators are a good idea but why not add proper __str__?)
- mabynogy 8y agoI use "star" in my programming language to "dereference" generators (run them until they are finished). For example: //block for 4s sleep* 4 //run a modal form let* ok form_confirm "Do you agree?" Those calls are converted to loops.
- nemoniac 8y agoIf you use pretty much any lisp-like language you can add your own favourite syntactic sugar to the language yourself.
- EvenThisAcronym 8y agoHands down, it's D's shorthand array operations. int[] a = [1, 2, 3]; int[] b = a[] * 3; assert(b == [3, 6, 9]); a[] += 2; assert(a == [3, 4, 5]); int[] c = a[] + b[]; assert(c == [6, 10, 14]); This of course works with D's slicing syntax so you can do stuff like a[0..1] *= 3.
- Doxin 8y agoI'm absolutely positively in love with "Universal function call syntax" from D, it makes the following: foo.bar(baz) compile to the following if foo has no property bar: bar(foo, baz) It allows you to trivially extend classes from libraries without meddling with their code or breaking other code using the library. e.g. if you define: string helloWorldize(string input){ return "Hello, "~input; } You can then do this anywhere "helloWorldize" is in scope: "bob".helloWorldize(); And because of the strong type system and smart compiler you'll never run into situations where you call helloWorldize when you don't mean to.
- snarfybarfy 8y agoMultiline strings aka 'here documents' in most Shells. Rich datastructure literals in Clojure for sets #{'foo'}, maps {:a 1, :b 2}, lists (1,2,3) vectors [1, 2, 3] The serialization format EDN is basically JSON on steroids. https://github.com/edn-format/edn https://github.com/edn-format/edn