Hacker News new | ask | show | jobs
by bmacho 1220 days ago
I tried to translate it to python, I translated

    (defn sum3
      "Solve the 3SUM problem in O(n^2) time."
      [s]

      (def tab @{})
      (def solutions @{})
      (def len (length s))

      (for k 0 len
        (put tab (s k) k))

      (for i 0 len
        (for j 0 len

          (def k (get tab (- 0 (s i) (s j))))

          (when (and k (not= k i) (not= k j) (not= i j))
            (put solutions {i true j true k true} true))))

       solutions)
into

    def sum3(s) :
        """Solve the 3SUM problem in O(n^2) time."""
    
        tab = {}
        solutions = {}
        l = len(s)
    
        for k in range(0,l) :
            tab[ s[k] ] = k
            
        for i in range(0,l) :
            for j in range(0,l) :
                
                k = tab.get( -s[i]-s[j] ) 
                
                if k and k != i and k != j and i != j :
                    solutions[ {i:True, j:True, k:True} ] = True
                    
        return solutions 
pretty much the same. Python is not working because it can't hash dicts, while janet interprets {1:True, 2:True} the same as {2:True,1:True} when these are keys (I think?).

In the example janet returns

    (map keys (keys solutions))
instead of the "solution" dict that converts dicts like {{1:True, 2:True} : True} into [[1,2]], but I don't get it how.

But syntactically janet is not much worse(?).

1 comments

One thing the Python version doesn't suffer from is lines that have to end in something like "))))". Syntax readability may be subjective, and I agree that the business logic in both examples are equally readable, but I think having to read and write a bunch of repeated punctuation at the end of a line, depending on how deeply the final statement is nested, is annoying. I don't know how Janet in particular handles error messaging around unmatched parens, but most languages have trouble localizing errors to the place where missing parens, curlies, etc actually are. This can be alleviated by rainbow highlighting paren pairs, or even having the editor auto-insert closing parens to make you less likely to forget one. But I think if you need additional help from the editor to make using the syntax a nice experience, that may be an objective sign that the syntax isn't the best.
You don't HAVE to write lines that way, though it is the convention which as a mostly outsider I've never been a huge fan of. Think about languages like c# where you often have multiple closing curly braces but the convention is separate lines. You could write them like Lisp if you wanted but no one does.
I assume "))))" is idiomatic because of the typical depth of nesting required in languages like this. If you always used newlines and indents to align the closing character, you'd waste a lot of vertical space. That's less of an issue in something like C# where you don't have to nest as deeply.
This is kind of unfair, unless you're in an indent based language you cannot get rid of this. The only other solution I've seen was in a pascal-like language, where you did end function NAME and that would close everything inside.
True, but there are two things languages like C have over this one: (1) Enclosing stuff in parens and curlies happens less often than they do in this one. So the depth of nesting is typically shallower. (2) The idiomatic way to handle closing multi-line blocks is to use newlines and indents to visually align the closing character with the start of the line containing the opening character. But, like a sibling comment points out, nobody does that and "))))" is idiomatic here, so I feel like it's a fair call-out.