Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

It's at least twice as noisy. It has more operators, more different punctuators, < > brackets in addition to ( ) and { }.

Not sure what error handling you have in mind, but it's robust. We can interactively call it from gdb with some garbage values:

  (gdb) r
  Starting program: /home/kaz/txr/txr-dbg 
  This is the TXR Lisp interactive listener of TXR 215.
  Quit with :quit or Ctrl-D on empty line. Ctrl-X ? for cheatsheet.
  1> (raise 5)

  Program received signal SIGTRAP, Trace/breakpoint trap.
  0x00132416 in __kernel_vsyscall ()
  (gdb) p do_eval_args(9, 9, 9, 9)
  Too few arguments in function call.
  (gdb) p do_eval_args(9, 9, 9, 9, 9)
  ** car: 2 is not a cons
  ** during evaluation at expr-1:1 of form (raise 5)
  ** run with --backtrace to enable backtraces
  2> _
The function relies on args having enough room for all the values; both callers ensure that. The lookup function can't be wrong, either.


What a strange comment. When compared to my first Rust snippet in my previous comment, your C code has more parens, the same number of brackets, more semi-colons, more asterisks and more inscrutable function pointer syntax. Of course, I don't actually find C's syntax all that noisy, but I don't find Rust's syntax particularly noisy either. Probably because I know both languages. But at least be fair and try to look at both with virgin eyes instead of only one of them.

The fact that it does error handling is not at all clear from its type signature, in contrast to Rust's function signature. So that's going to contribute "more noise" from your perspective, but on the flip side, it also conveys more information. Based on your demonstration, it looks like your function just aborts the program on an error, but the Rust function is a bit more versatile. It gives the caller a choice of how to deal with an error. Otherwise, I could just write this instead:

    fn eval_forms(arg_forms: &[RispExp], env: &mut RispEnv) -> Vec<RispExp> {
      arg_forms.iter().map(|x| eval(x, env)).collect()
    }


Since we're working on Lisp internals, we can accept a few parentheses.

The code has two asterisks, both in parameter declarations, indicating pointers.

It has exactly one binary operator in the body, the assignment = denoting the one local side effect (stepping the iteration variable of the simple for (;;) loop).

All else is simple function calls. Except for the function pointer declaration, and perhaps not knowing car and cdr, an Awk or JS programmer might grok this.

The program doesn't abort; the exception was caught in the REPL. We were thrown right out of the GNU Debugger where we caused the problem, and back into the Lisp REPL. We can demonstrate that in other ways, like this:

  (gdb) r
  Starting program: /home/kaz/txr/txr-dbg 
  This is the TXR Lisp interactive listener of TXR 215.
  Quit with :quit or Ctrl-D on empty line. Ctrl-X ? for cheatsheet.
  1> (catch (raise sig-trap) (error (x) (put-line `caught error: @x`)))

  Program received signal SIGTRAP, Trace/breakpoint trap.
  0x00132416 in __kernel_vsyscall ()
  (gdb) p car(9)
  caught error: car: 2 is not a cons
  t
  2> (+ 2 2)
  4
  3> _
gdb gets confused here, though:

  3> (exit 0)
  [Inferior 1 (process 8529) exited normally]
  The program being debugged exited while in a function called from GDB.
  Evaluation of the expression containing the function
  (car) will be abandoned.
Quite understandably, it doesn't understand the exception handling and didn't notice that we jumped out; it still thinks we are executing the car function. Oh well!




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: