Hacker News new | ask | show | jobs
by kazinator 1857 days ago
> I would be interested in seeing anything that was shorter

One way to do that would be to pose that as a problem on the Code Golf Stackexchange.

My rewrite-case solution condenses (by removal of all non-essential spaces) to 69 bytes if the symbols are in a hash table K, and the input list is in a variable y, rather than a big literal:

  (rewrite-case x y((@[K @sym]* . @rest)^(,sym _ . ,rest))(@else else))
A one-letter name could be chosen for the macro. Furthermore, one-letter names could be chosen for sym, rest and else:

  20> (r x y((@[K @s] * . @r)^(,s _ . ,r))(@e e))
  (foo bar * select _ fox where _ bravo)
Still working! Now down to 43 bytes.

(It's not because I cannot that I do not do this with all my code.)

Doh, why use . ,r in the backquote if we are golfing? That should be ,*r: using the splice operator, like Common Lisp's or Scheme's ,@, getting us to 42 bytes:

  20> (r x y((@[K @s] * . @r)^(,s _ ,*r))(@e e))
  (foo bar * select _ fox where _ bravo)
I suspect Code Golf Stackechange regulars could get it down to way in one of the dedicated golfing languages like Retina or what have you.*

What else can we do? The @[K @s] predicate syntax could be replaced by a custom operator defined by defmatch, looking like @(K s).

  21> (defmatch k (sym) ^@[K (sys:var ,sym)])
  k
  22> (r x y((@(k s) * . @r)^(,s _ ,*r))(@e e)) ;; 41
  (foo bar * select _ fox where _ bravo)
Just noticed the ) * is not fully golfed:

  23> (r x y((@(k s)* . @r)^(,s _ ,*r))(@e e)) ;; 40
  (foo bar * select _ fox where _ bravo)
The k pattern operator macro could be non-hygienic: it could implicitly bind a variable called s:

  24> (defmatch k () ^@[K @s])
  k
  25> (r x y((@(k)* . @r)^(,s _ ,*r))(@e e)) ;; 38
  (foo bar * select _ fox where _ bravo)
These last few feel like cheating because they are too special purpose. Defining anything you can only possibly use just once isn't making the overall program smaller.
2 comments

Also-rans:

  1> [window-map 1()(do if(and[K @1](eq'* @2))'_ @2)y]
  (foo bar * select _ fox where _ bravo)
  2> (mapcar(do if(and[K @1](eq'* @2))'_ @2)(cons()y)y)
  (foo bar * select _ fox where _ bravo)
  3> (mapcar(lambda(:match)((@[K] *)'_)((@a @b)b))(cons()y)y)
  (foo bar * select _ fox where _ bravo)
you'll never get J/K brevity though. Because in opposition to Lisp where control flow is explicit in the syntax, most of the control flow in array languages is implicit. I love lisp too, but for some (rare) use cases it's not the best.
You will never get J/K brevity by writing a condensed for of normal Lisp because spaces are often required to separate tokens.

You can get implicit control flow via macros.

Furthermore, all control flow is implicit is some way.

Take basic old progn: (progn (foo) (bar)) evaluates (foo) and then control implicitly passes to (bar) because that's the next thing.

The only control flow which is not implicit is that of a state machine described by a table or graph, indicating the next state for every input and current state.

(How can you say you can't get implicit control flow in Lisp, when I'm using pattern matching to express if you see this prefix, replace it with that?)

Speaking of macros, you could always resort to a macro like this:

  (j"... line noise in character string ...")
The j macro expands the string to code at compile time. The code could be a bona fide J implementation, or something like it. That's still not down to J, because of the (j"") wrapping chewing up five characters. In a Lisp with a programmable read table, that could be reduced to two character framing or something.