Arc Forumnew | comments | leaders | submitlogin

Hey thanks this works great. I just need to fix an easy bug in the C code for pop.

Most of those errors are saying it can't find a global variable named "stack". That's because when you do (= stack (newSA)), you're creating a global variable called "stack" in Arc but it's called "_stack" in Racket. In your macros, you're generating Racket code that uses the Arc variable name, so it's looking for a "stack" Racket global that doesn't exist. You can potentially fix this in your macros... but why use macros when you already have functions that do what you want? :)

  (= newSA $.newStackArray)
  (= deleteSA $.delete)
  (= pushSA $.pushStackArray)
  (= popSA $.popStackArray)
  (= fullSA? $.fullStackArray)
  (= emptySA? $.emptyStackArray)
  (= displaySA $.displayStackArray)
If you absolutely need macros, then here's a fixed version of pushSA that embeds its arguments as Arc expressions rather than Racket expressions:

  (mac pushSA (stack x)
    `( ($:lambda (stack x)
         (pushStackArray stack x))
       ,stack ,x))
  ; or...
  (mac pushSA (stack x)
    `($.pushStackArray ,stack ,x))
Fixing the others would be similar, but I picked pushSA as an example because it has two arguments.

Finally, I think this line just has a simple typo:

  typo:  (emptytSA? stack)
  fix:   (emptySA? stack)
How far does this get you? I haven't tried your code, and I don't know if this will fix all your problems, but maybe it's a start!

Thanks mate, below are the error codes:

  (= stack (newSA))
  #<cpointer>

   (pushSA stack 1)
  stack: undefined;
   cannot reference undefined identifier
    context...:
     /home/conan/Documents/anarki-master/ac.scm:1225:4

  (fullSA? stack)
    stack: undefined;
   cannot reference undefined identifier
    context...:
   /home/conan/Documents/anarki-master/ac.scm:1225:4

  (empytSA? stack)
  _empytSA?: undefined;
   cannot reference undefined identifier
    context...:
   /home/conan/Documents/anarki-master/ac.scm:1225:4

  (displaySA stack)
  stack: undefined;
   cannot reference undefined identifier
    context...:
   /home/conan/Documents/anarki-master/ac.scm:1225:4

  stack
  #<cpointer>

  Here is the C code:

  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include "StackArray.h"

  void pushStackArray(StackArray * stack, int item){
	if(stack->size < MAX){
		stack->array[stack->size] =  item;
		stack->size++;
	} else {
		printf("The stack is full\n");
	}
  }

  int popStackArray(StackArray * stack){
	if(stack->size > 0){
		stack->size--;
	} else if(stack->size == 0){
		printf("Stack array is empty\n");
	}
	return stack->array[stack->size + 1];
  }

  int fullStackArray(StackArray * stack){
	return stack->size == MAX ? 1 : 0;
  }
  int emptyStackArray(StackArray * stack){
	return stack->size == 0 ? 1 : 0;
  }

  StackArray * newStackArray(){
	StackArray * stack = malloc(sizeof(StackArray));
	int i;
	for(i = 0; i < MAX; i++){
		stack->array[i] = 0;
	}
	stack->size = 0;
	return stack;
  }

  void displayStackArray(StackArray * stack){
	int i;
	for(i = 0; i < stack->size; i++){
		printf("%d ", stack->array[i]);
	}
	printf("\n");
  }

  void delete(StackArray * stack){
	free(stack); 
  }

Can you share the error you get and the c file so I can try to reproduce?
5 points by kogir 3992 days ago | link | parent | on: Why and how is Hacker News so fast?

It's fast because it's not bloated. It returns fairly minimal (if not elegant) HTML, and loads few additional resources.

The HN front page is about 7kB - many times smaller than even minimized jQuery (83kB as of 2.1.4).

The data is small and all fits in RAM on a single server during normal operation, so there's no additional network latency hitting a DB over the network.

----- Edit: Oops - missed that this was a link.

2 points by rocketnia 3992 days ago | link | parent | on: Why parents?

I think those simplifying assumptions are consistent with what dagfroberg was saying. I think "Polish notation" and "shunting-yard algorithm" make sense as terminology here, even if dagfroberg and I might each have slight variations in mind.

---

"so no higher-order functions"

I think we can get read-time arity information for local variables, but only if our read-time arity information for the lambda syntax is detailed enough to tell us how to obtain the arity information for its parameter. For instance...

  -- To parse 3: We've completed an expression.
  3 =:: Expr
  
  -- To parse +: Parse an expression. Parse an expression. We've
  -- completed an expression.
  + =:: Expr -> Expr -> Expr
  
  -- To parse fn: Parse a variable. Parse an expression where that
  -- variable is parsed by (We've completed an expression.). We've
  -- completed an expression.
  fn =:: (arg : Var) -> LetArity arg Expr Expr -> Expr
  
  -- To parse letArity: Parse a variable. Parse an arity specification.
  -- Parse an expression where that variable is parsed by that arity
  -- specification. We've completed an expression.
  letArity =:: (arg : Var) -> Arity n -> LetArity arg n Expr -> Expr
  
  -- To parse arityExpr: We've completed a specification of arity
  -- (Expr).
  arityExpr =:: Arity Expr
  
  -- To parse arityArrow: Parse a specification of some arity m. Parse a
  -- specification of some arity n. We've completed a specification of
  -- arity (Parse according to arity specification m. We've completed a
  -- parse according to arity specification n.).
  arityArrow =:: Arity m -> Arity n -> Arity (m -> n)
  
  -- ...likewise for many of the other syntaxes I'm using in these arity
  -- specifications, which isn't to say they're all *easy* or even
  -- *possible* to specify in this metacircular way...
This extensible parser is pretty obviously turning into a half parser, half static type system, and now we have two big design rabbit holes for the price of one. :)

Notably, Telegram's binary protocol actually takes an approach that seems related to this, using dependent type declarations as part of the protocol: https://core.telegram.org/mtproto/TL

3 points by akkartik 3992 days ago | link | parent | on: Why parents?

"We can't parse ... unless we know all the operators that it uses."

Yes, that was my reaction as well. I thought https://en.wikipedia.org/wiki/Polish_notation requires either a clear separation between operators and values (so no higher-order functions) or all operators to be binary. Parentheses (whether of the lisp or ML or other variety) permit mult-iary higher-order operations.

Also, doesn't https://en.wikipedia.org/wiki/Shunting-yard_algorithm require some sort of delimiter between operations? I thought it didn't work for nested operations without commas or parens, or the simplifying assumptions in the previous paragraph.

3 points by rocketnia 3992 days ago | link | parent | on: Why parents?

Much of what you're saying sounds feasible and even familiar. Removing parens from Lisp and adding infix operators is a popular idea, popular enough that we've made a list of projects that explore the possibilities:

https://sites.google.com/site/arclanguagewiki/more/list-of-l...

---

As I've learned more about the ML family of language syntax (e.g. SML, OCaml, Haskell, Elm, Agda, Idris), I've come to the conclusion that ML-style language designs treat their syntax as s-expressions anyway. Where Lisp function call expressions are nested lists, ML expressions are nested "spines." ML languages treat infix spines as sugar for prefix spines, just like we're talking about for Lisp.

  gcd (a + b) (c - square d)           (* ML *)
  (gcd (+ a b) (- c (square d)))       ; Lisp
  (gcd ((+) a b) ((-) c (square d)))   (* ML again *)
In terms of precedence, ML's prefix calls associate more tightly than infix ones. That's the other way around from Arc, where the infix syntaxes associate more tightly than the prefix ones:

  (rev:map testify!yes '(no no yes))  ; returns (t nil nil)
I think ML's choice tends to be more readable for infix operators in general. The alternative form of the gcd example would look like this:

  gcd a + b c - (square d)
In this example, the + and - look like punctuation separating the phrases "gdc a", "b c", and "(square d)", and it takes me a moment to realize "b c" isn't a meaningful expression.

So I think the ML syntax is a good start for Lisp-with-syntax projects. For the syntax I've been designing, I've stuck with Lisp so far, but I want to figure out a good way to integrate ML-style syntax into it.

---

That said, there's a reason I've stuck with Lisp for my syntax: We can't parse ML syntax into nested spines unless we know all the operators that it uses. If we want to support custom infix operators, then the parser becomes intertwined with the language of custom operator declarations, and we start wanting to control what operator declarations are created during pretty-printing. These extra moving parts seem like an invitation for extra complexity, so I want to be careful how I integrate ML-style infix into my syntax, if at all.

1 point by dagfroberg 3992 days ago | link | parent | on: Why parents?

... or you want it the other way? Then the next step is easy to put back parenthesis.. parse it and write parenthesis back around each construct. Put it then in Lisp interpreter. Will it run after such a prettyprinter juggling?
2 points by dagfroberg 3993 days ago | link | parent | on: Why parents?

... oh, why did I mentioned Shunting Yard that's the most "unlispy"? Well it ensures the code translates to "Lisp without parenthesis"! Write with '(' and ')' if you want, it will remove it in the prettyprint intermediate code anyway. And you even write mathematical expressions in a usual way and the outcome will be prefixed! Your problems are solved..
2 points by zck 3997 days ago | link | parent | on: Website with arc

Obviously Arc is somewhat of an unconventional choice, so you might run into more problems. I'm not saying that to discourage you, just to make you aware of what you're getting into.

You might also look into Clojure, if you want something with more libraries.

But if you decide on Arc, I'd say (as usual) that you can just do development on whatever machine you're working on -- you won't be doing anything heavyweight enough that you need a separate dev machine.

Having not run Arc in production, I'll defer to akkartik's suggestions for picking a cheap VPS.

3 points by akkartik 3998 days ago | link | parent | on: Website with arc

You would have to write code in Arc or Racket, I think. In common lisp I see http://www.cliki.net/cl-eshop on http://www.cliki.net/web.

For hosting there's tons of cheap unix VPS providers. Not much differentiating them; just go with one, and you can switch if you don't like it. Start with https://linode.com or https://www.digitalocean.com.

3 points by jsgrahamus 4026 days ago | link | parent | on: Automatic bug repair

Interesting article. Will the next step be computers writing their own programs?
1 point by akkartik 4032 days ago | link | parent | on: Parallelism and Data Oriented Design

I'm starting to feel old :) I've been programming for 16 years now.

Feel free to ask me more questions. I'm not looking for help, rather to help. But there's still some way to go. In the meantime I'll help in any other way. Valgrind is super useful for C programming.

2 points by cthammett 4032 days ago | link | parent | on: Parallelism and Data Oriented Design

Impressive project, how long have you been programming for? I'm not sure if I can be of much technical assistance but if you recommend a few tools I could probably learn more about testing and find bugs. Earlier this week I installed valgrind to check for errors and memory leaks and I'm looking for a debugger that will work with lubuntu. I am also learning assembly.
2 points by akkartik 4032 days ago | link | parent | on: Parallelism and Data Oriented Design

Thanks for trying it! It's not actually a Lisp :) Check out the examples in the readme.

The repl is sadly not done. Repl feels like the wrong metaphor. I'm writing on a more useful version in edit.mu, but that's far from done. For now sadly you have to type code into a file and run it as a separate step. Just for a couple more weeks, hopefully.

2 points by cthammett 4033 days ago | link | parent | on: Parallelism and Data Oriented Design

The project looks interesting. I would like to learn more about assembly to, have greater understanding and control over what my computer actually does. All the tests passed but I made mu crash using repl.mu, if this help in finding bugs?

  ./mu repl.mu
  ready! type in an instruction, then hit enter. ctrl-d exits.
  (+ 1 1)
  missing type in {name: "1", properties: ["1": ]}
  mu: 041name.cc:82 bool disqualified(reagent&): Assertion `!x.types.empty()' failed.
  Aborted (Core dumped)
Also my left, middle and right mouse button clicks were printing rubbish to the terminal after that. I restarted the terminal and mouse functionality was normal again.
1 point by akkartik 4034 days ago | link | parent | on: Parallelism and Data Oriented Design

No reason they couldn't!

If you're into assembly I'd love to hear what you think of my current project to teach programming using a sort of idealized assembly: http://github.com/akkartik/mu. I'm co-designing the assembly language with the OS around it, in the spirit of C+unix.

2 points by cthammett 4034 days ago | link | parent | on: Parallelism and Data Oriented Design

Thanks, I didn't see anything suspect. It should be a good learning experience calling c from Anarki. I saw a tutorial today how to create c callable functions using NASM x86-64 assembly code and it worked. Do you think assembly and Anarki can talk to each other through c?
2 points by akkartik 4036 days ago | link | parent | on: Parallelism and Data Oriented Design

In the past I just used the Racket FFI for C with anarki's $ operator.

Hold on, let me throw up this arc project of mine from many years ago. The FFI isn't on head, but here's how I imported a Porter stemming (https://en.wikipedia.org/wiki/Stemming) implementation and a keyword-guessing algorithm in C: https://github.com/akkartik/readwarp/blob/e281ecfefd/keyword.... C functions that that invokes: https://github.com/akkartik/readwarp/blob/e281ecfefd/keyword...

(There's a password for my mail delivery service in that repo, but that account is now defunct. Hopefully nothing else is confidential. Please be nice and let me know if you see something there that might damage me :)

2 points by cthammett 4037 days ago | link | parent | on: Parallelism and Data Oriented Design

Thanks for the tips, I'll keep on exploring the possibilities. On a side note, is there a c or python ffi for Anarki?
2 points by akkartik 4038 days ago | link | parent | on: Parallelism and Data Oriented Design

Nice! I should warn you that arc is very deeply permeated with the assumption that there's only one thread of execution. See atomic, for example, which all the assignment operators use: https://arclanguage.github.io/ref/atomic.html. Couple with the statement that "The distinction between “future safe” and “future unsafe” operations may be far from apparent at the level of a Racket program," (http://docs.racket-lang.org/guide/parallelism.html) and I think you might be in for some interesting debugging times :)

Hmm, future-event seems like it's just for performance logging? Maybe ignore it for now and try to build something non-trivial with the primitives you have?


yep

To try it out (on linux, or Mac with GNU tools):

  $ git clone https://github.com/akkartik/mu
  $ cd mu
  $ make
  $ ./mu chessboard.mu
More information: http://github.com/akkartik. Why I'm working on this instead of lisp: http://akkartik.name/about (tl;dr - I'm building better foundations for runtimes for implementing languages. This has been my long-standing itch: http://arclanguage.org/item?id=17598)

(at git hash dff767144b2)

2 points by rocketnia 4075 days ago | link | parent | on: GTK-server

  (define-values (*gtk-in* *gtk-out* _) (process "gtk-server -stdin"))
Well, Arc doesn't have a way to open processes that take stdin. Fortunately, Racket does, and if you're using Anarki, the $ macro makes it easy to write little pieces of Racket code in your Arc programs when necessary.

Racket's interface for (process ...) might be a bit different than Chicken Scheme's, so I found the documentation here: http://docs.racket-lang.org/reference/subprocess.html.

  (let (i o . ignored) ($.process "gtk-server -stdin")
    (= gtk-in i)
    (= gtk-out o))
The ($.process ...) call returns a list, and (let ...) destructures that list to make local bindings for i and o. This doesn't set up any global bindings, so I do that inside the (let ...).

---

I have a few corrections for this:

  (def gtk str
    (write str gtk-out)
    (if (~is "gtk_server_exit")
      (read-line gtk-in)))
Here's the corrected version:

  (def gtk (str)
    (disp (+ str "\n") gtk-out)
    (if (~is str "gtk_server_exit")
      (readline gtk-in))
The biggest difference is that I'm using (disp ...) where you were using (write ...). The functionality of (write ...) is to output s-expressions according to the same syntax you write code with, and this means written strings will always have quotation marks around them, which probably isn't what you want.

---

Thanks for exploring these interesting topics. :)

1 point by cthammett 4081 days ago | link | parent | on: Let Over lambda, Ch 6 Ichain intercept

Thank you for the tips and corrections.
2 points by rocketnia 4081 days ago | link | parent | on: Let Over lambda, Ch 6 Ichain intercept

Hmm, looking at the implementation, 'alet is a utility for wrapping a lambda to do various things:

a) The letargs let you set up some bindings the function can refer to.

b) The body lets you do some things with the function in scope before returning it.

c) It wraps the function in a mutable binding named 'this, and it actually returns another function that dereferences this binding and calls whatever's inside. That way you can dynamically replace the entire behavior of the function by assigning to 'this.

So it seems to be geared for a certain object-oriented style where objects have a) private fields, b) a programmable constructor, and c) a private "become" operation.

It looks like 'dlambda is some kind of a multi-branch, destructuring lambda. In this context of this object-oriented style, it effectively lets your object have multiple methods.

2 points by rocketnia 4081 days ago | link | parent | on: Let Over lambda, Ch 6 Ichain intercept

I think you might have made a slight mistake translating 'alet. Here's a minimal fix:

   ;Anaphoric let
   (mac alet (args . body)
  -  `(with ,args
  +  `(with (this nil ,@args)
        (assign this ,(last body))
        ,@(butlast body)
        (fn params
          (apply this params))))
The code probably seemed to be working, but it was actually setting a variable 'this from the surrounding scope rather than its own 'this.

In a way it's fitting to bring that up, because 'alet-fsm is designed to modify the 'this from the surrounding scope....

Er, speaking of which, your translation of 'alet-fsm is pretty surprising. (You're assigning a bunch of nonlocal variables, and you're even redefining a global macro at run time, which is usually too late because the program has already been macroexpanded. Furthermore, instead of returning the first state of the FSM, you're returning the implementation of a macro.) I'll start from the original Common Lisp code:

  (defmacro alet-fsm (&rest states)
    `(macrolet ((state (s)
                  `(setq this #',s)))
       (labels (,@states) #',(caar states))))
While Arc doesn't have (macrolet ...), in this case we can achieve something very close by just making this macro global, since it has no local dependencies.

  (mac state (s)
    `(assign this ,s))
What (labels ...) does in Common Lisp is introduce some local variables that hold functions, in such a way that every function's definition can see every other function. To keep my code simple to read, I'm going to resort to a utility from Anarki that achieves the same kind of scope, namely (withr ...):

  (mac alet-fsm states
    `(withr ,states
       ,car.states))
The expansion of (withr (a (fn ...) b (fn ...) c (fn ...)) ...) is something like this:

  (with (a nil b nil c nil)
    (assign a (fn ...))
    (assign b (fn ...))
    (assign c (fn ...))
    ...)
Note how the local variables are introduced in a (with ...) scope that fully surrounds the (fn ...) expressions, so all the variables are in scope for all the functions.
2 points by rocketnia 4081 days ago | link | parent | on: Let Over lambda, Ch 6 Ichain intercept

Hmm... I haven't looked at the whole context of what you're doing. but I see you said "The macrolet conversion is where I am having difficulties." That makes sense. Arc doesn't have macrolet! (I think even Anarki doesn't have it... does it?)

Generally, I'd try to convert (macrolet ...) into local functions instead of local macros.

I don't know Common Lisp very well, but judging by the "surprising" example at http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node85.html, maybe there was no particular reason for this example to use (macrolet ...) in the first place:

   (defmacro! ichain-intercept (&rest body)
     `(let ((,g!indir-env this))
        (setq this
          (lambda (&rest ,g!temp-args)
            (block ,g!intercept
  -           (macrolet ((intercept (v)
  -                       `(return-from
  -                          ,',g!intercept
  -                          ,v)))
  +           (flet ((intercept (v)
  +                    (return-from
  +                      ,g!intercept
  +                      v)))
                (prog1
                  (apply ,g!indir-env
                         ,g!temp-args)
                  ,@body)))))))
(I haven't tested this.)

At this point, the code can be translated to Arc, and then it can be simplified dramatically:

  (point ,intercept
    (let intercept (fn (v) (,intercept v))
      ...))
  
  -->
  
  (point ,intercept
    (let intercept ,intercept
      ...))
  
  -->
  
  (point intercept
    ...)
This ends up simplifying to the exact same code as ichain-intercept%.

I think that makes sense. This example only accomplished the convenience of writing (intercept acc) instead of (return-from intercept acc), but your Arc code already had (intercept acc) to begin with.

1 point by akkartik 4081 days ago | link | parent | on: Let Over lambda, Ch 6 Ichain intercept

Remind us, what is alet? I tried reading http://letoverlambda.com/index.cl/guest/chap6.html but it uses vocabulary from previous chapters, like dlambda.
More