Arc Forumnew | comments | leaders | submit | skenney26's commentslogin
1 point by skenney26 6401 days ago | link | parent | on: let redundant to with?

let is just a convenience that allows you to type fewer parens:

  (let x 1
    (pr x))

  (with (x 1)
    (pr x))
I agree with you that it seems a little awkward to have so many macros just for binding local variables (let, with, withs).

-----

2 points by absz 6401 days ago | link

withs is actually fundamentally different in that the binding order is different; something defined later can refer to something defined earlier.

-----

1 point by bOR_ 6401 days ago | link

If there a way in which arc would understand

  (with x 1
     (pr x))
as well as

  (with (x 1 y 2)
     (pr x))
... initially, it would seem that you can distinguish the two by whether there's a ( following the with, but you might get into trouble:

  (let (x y) mylist
     (pr x y)
where let is followed by a (. mmm. I'm a still quite unfamiliar with arc or lisp. Can anyone give an example in which interchanging the "let" for a "with" or visa versa changes the meaning of the function?

-----

4 points by absz 6401 days ago | link

You yourself gave an example. The fact that Arc allows destructuring (that is, writing (let (a b) lst ...)) means that the presence of a list is not an adequate indicator of whether you're letting or withing. And without that, how do you know when you're done defining variables? If you don't parenthesize them, they could go on forever. The only other option is to remove the implicit do in let/with; that way, only the last statement would be run, and the first n would be variable bindings; to run more than one, you would use do.

-----

2 points by bOR_ 6401 days ago | link

Got it :)

  arc> (= b "abba")
  "abba"
  arc> (let (a b) (list 1 2) (pr a b))
  121
  arc> b
  "abba"
  arc> (with (a b) (list 1 2) (pr a b))
  abbaabba"abba"
  arc>

-----

3 points by eds 6400 days ago | link

Yes, you can, but you might have to sacrifice the implicit 'do block in 'let. See http://arclanguage.org/item?id=3234.

That said, it might be good to remove the implicit 'do anyways, since as pg has said, an explicit 'do highlights non-functional code. Combining 'let and 'with would just be a convenient side effect.

P.S. If I am not mistaken I think this would also allow you to do destructuring as well...

-----

3 points by absz 6400 days ago | link

This is actually fairly simple to write (first defining butlast for convenience):

  (def butlast (seq)
    " Returns every element of `seq' but the last one.
      See also [[last]] [[cut]] "
    (cut seq 0 -1))
  
  (mac letn parms
    " Simultaneously ssigns the given (unparenthesized) local variables in the
      one-statement body.
      See also [[let]] [[with]] [[letns]]"
    `(with ,(butlast parms) ,(last parms)))
  
  (mac letns parms
    " Sequentially assigns the given (unparenthesized) local variables in the
      one-statement body.
      See also [[let]] [[with]] [[letn]]"
    `(withs ,(butlast parms) ,(last parms)))
Then letn is like with, but unparenthesized, and letns is like withs, but unparenthesized. (letn = "let n variables".) And yes, destructuring works.

-----

2 points by eds 6400 days ago | link

Perhaps these should be added to Anarki?

-----

1 point by absz 6400 days ago | link

Probably would make sense, but I'd rather wait until we had better names (I don't particularly like these.) Thoughts?

-----

2 points by almkglor 6398 days ago | link

'where ?

  (where foo (some-expression)
         bar (hmm that)
    (some-fn foo bar))

  (wheres val    (another-expression)
          grind  (grr val)
    (that-fn val grind))

-----

3 points by absz 6398 days ago | link

That's not bad... given?

  (given s1 (zebda oualalaradime)
         s2 (cake  symphony in c)
    (play s1 s2))
  
  (givens arc (language-by             pg)
          mzs (implementation-language arc)
    (run-in arc mzs))

-----

3 points by skenney26 6398 days ago | link

Okay, for some reason I can't get this out of my head.

What if "let" becomes "as", given becomes "let", and givens becomes "lets"?

-----

1 point by absz 6398 days ago | link

I would be reluctant to change let, since it's a standard operation in arcN.tar. Otherwise, there's probably some merit to that.

-----

3 points by eds 6398 days ago | link

And now we're back to waiting for pg to do something ;)

-----

1 point by almkglor 6398 days ago | link

Heck no. We can do this ourselves. Remember, the textual transformation to transform let's is just that: a textual translation. It should be possible to create an automated translation tool (based off raymyers' treeparse) that will handle this for us.

Let the old version of 'let be Arc2Let, and the proposed new let be Arc2.7Let. Let the old version of 'with and 'withs be Arc2With and Arc2Withs, respectively. We need to determine if each Arc2Let in the source is composed of a single expression in the body. If it is, we leave it as-is. If it isn't, we simply replace it with Arc2.7As.

For each Arc2With we determine if the body is composed of a single expression. If it is, we replace it with Arc2.7Let, removing the parens around the Arc2With bindings. If it isn't, we leave it as-is. Ditto for Arc2Withs, replacing it with Arc2.7Lets.

We define an expression simply as a sequence of whitespace, base-expression, and whitespace. We define whitespace as being either a comment (either #||# or ;) or ordinary whitespace.

A base-expression is simply a symbol, a number, a character, a string, a quote-expression, a comma and comma-at expression, or a list. A quote-expression is simply the ' quote or ` backquote character followed by maybe whitespace, followed by an expression; comma and comma-at are defined similarly. A list is composed of an opening parenthesis followed by many expressions, followed by a closing parens.

We can determine if a 'let form has several expressions by defining two variants of a 'let form. An Arc2Let is composed of ( <maybe whitespace> let <whitespace> <expression> <expression> <expression> [many <expression>]), and that we have to transform to Arc2.7As (by filtering out the let expression using treeparse 'filt). An Arc2.7LetCompatible is composed of just (let <expression> <expression> <expression>), which we do not transform.

----

Of course, this does represent a veritable fork of the Arc code ^^.

-----

1 point by absz 6398 days ago | link

I would leave with and withs alone, so that we have the option of the implicit do (also because it makes it easier to implement given/Anarki-let :P). And why not use a code-tree-walker if we want to do this—isn't that the point of Lisp?

Still, I don't quite think the fork is worth it….

-----

2 points by almkglor 6397 days ago | link

Actually the point of messing with the existing 'with / 'withs is to force the programmer to consider using the new form of 'let. ^^

The problem of using a code-tree walker is: you lose the comments, which are arguably about 50% the value of the code.

-----

1 point by absz 6397 days ago | link

Right, comments. Just a little important, aren't they? :P

You raise a good point... it's the same number of parentheses either way. But in that case, why not just have let and lets (as given(s)), and be done with it?

-----

3 points by almkglor 6397 days ago | link

> let and lets (as given(s))

Done and on the git ^^

Edit: as an aside, given that pg has said that he'll modify Arc as if there's nobody else programming in it, and that he does not appear to be using Anarki, eventually when Arc3 does come around, it is very possible that Anarki will be incompatible with Arc3. We may very well need to build a converter program in the future to transform Arc2-base Anarki to Arc3-base Anarki, so my abstract nonsense may very well be necessary in the future.

-----

1 point by absz 6397 days ago | link

Thanks!

And general abstract nonsense is almost always a good thing... still, that is worrisome.

-----

1 point by almkglor 6398 days ago | link

'given looks good - I think it's better than 'where.

-----

1 point by almkglor 6400 days ago | link

'these?

  (these x y
         r v
    (foo x r))
Of course it turns into 'theses ....

-----

2 points by skenney26 6399 days ago | link

Interesting idea. I like "as".

-----

2 points by almkglor 6399 days ago | link

  (as var x
      foo 42
    (something var foo))
Hmm...

But how about withs ?? == ass? ^^

-----

1 point by skenney26 6398 days ago | link

Think of it as short for assign :)

-----

1 point by skenney26 6398 days ago | link

How about "as" and "az"?

-----

5 points by absz 6390 days ago | link

I've been programming with given(s) for a little while now, and I really like it. Can't say why I'm so vehement, but it's definitely a Good Thing™. Thank you for bringing this up again (and a "thank you" to aidenn0, if he/she is still reading these fora, for suggesting this in the first place).

-----

3 points by almkglor 6390 days ago | link

An interesting bit about 'givens is that it makes functional programming in an imperative style almost seamless:

  (givens f (car n)
          v f!v
          _ (prn v) ; v isn't being set properly in some cases for some reason...
          l (combinatorics f v)
          _ (prn l) ; debugprint
    (is l 'undef))

-----

2 points by bOR_ 6390 days ago | link

I'm not on anarki, but I've followed this discussion. If you use given rather than let and with, which of the two options below would come out?

arc> (= b "abba") "abba" arc> (let (a b) (list 1 2) (pr a b)) 121 arc> b "abba" arc> (with (a b) (list 1 2) (pr a b)) abbaabba"abba" arc>

-----

2 points by absz 6390 days ago | link

  arc> (given (a b) (list 1 2)
         (pr a b))
  121
The difference between given and let/with is that you cannot have more than one statement in the body of the given. For instance:

  arc> (given (a b) (list 1 2)
         (prn "Here")
         (pr a b))
  Error: "Can't understand fn arg list \"Here\""
What's happening here is that given is trying to bind (prn "Here") to (pr a b), but (naturally) can't bind a string; it takes the first n args, where n is the largest even number less than or equal to the number of arguments provided, and interprets them as variables. You must, therefore, write

  arc> (given (a b) (list 1 2)
         (do
           (prn "Here")
           (pr a b))
  Here
  121
.

Also, I highly recommend switching to Anarki. It's got bugfixes and enhancements galore (and even runs on the newest version of mzscheme).

-----

4 points by bOR_ 6389 days ago | link

So the main drawback of given is that you need to make your do explicit? mmm, I never liked it implicitly anyway ;).

-----

3 points by absz 6389 days ago | link

It's the only "drawback", if such it is. I feel that since you need extra parentheses for either the body or the variables, it's better to wrap the body in a do, since that's less common.

-----

2 points by skenney26 6401 days ago | link | parent | on: using scheme libraries

Wouldn't it be more intuitive if $ returned a scheme function and applied it to the arguments?

  ($ asin x)

-----

5 points by absz 6401 days ago | link

To get that, you can write

  ($.asin x)
; in fact, that's often what I do. But being able to write snippets of Scheme can be important, if you need to work with things (for instance, datatypes like the boolean) which don't exist in Arc.

-----

1 point by skenney26 6402 days ago | link | parent | on: Printing squares

defcall looks interesting. Is there any documentation on other uses of it?

I like the idea of using the .. syntax:

  (spaces:map sq 1..5)

-----

4 points by absz 6402 days ago | link

defcall is pretty simple to use. The syntax is the same as that of def, except instead of a function name, you provide the type of the object. The function receives both the objects and its "arguments". E.g.

  arc> (defcall sym (self n)
         (repeat n (prn self))
  #<procedure>
  arc> ('a 3)
  a
  a
  a
  nil

.

-----

2 points by skenney26 6412 days ago | link | parent | on: One-to-many, many-to-many, etc

What does your current database look like? What relationships are you hoping to add?

I assume you're using deftem to define your database objects. I was thinking that it would helpful to have a version of deftem that automatically created defops for adding, updating, and deleting objects from a database (similar to Rails scaffolding).

-----

1 point by wfarr 6412 days ago | link

I know someone made scaffolding work earlier, but I don't know exactly how they did it.

Anyway, ideally with templates -- in my case, one for posts and one for tags -- you'd be able to make use of this relation in a functional way with no real performance issues.

-----

3 points by drcode 6412 days ago | link

I was the one who created the scaffolding system- It does, indeed, generate the code to add/update/etc from a database. I've continued to expand the system on my own, but since there wasn't much interest in the arc forum I decided not to continue checking code into anarki for now, but may again in the future- So right now it is strictly ver 0.01, though I'm surprised others seem to manage without a scaffolding system...

As for the issue of one-many and many-many, I guess I would suggest that in a one-to-many situation I would try and store the "many" as a child field in the "one", not use two separate tables if you can get away with it (one of the advantages of a non-RDBMS is that this design is possible)

As for many-many, I would probably have two tables, then have an extra table that just maps keys to keys for the two tables. Basically, just like an RDBMS association table. (or maybe even a bidirectional table, if you need to go "both ways")

If you want to know the "official" way to store data in different relationships in a simple, purely functional, memory resident database, I'd look at HApps-ixset. This is philisophically closely aligned to what you'd need in arc and is designed by some super smart guys. Unfortunately, their documentation is wanting or I'd point you to a good link that describes how to use it.

Those are some thoughts.

-----

2 points by skenney26 6411 days ago | link

I've been thinking it might be possible to make these mappings implicit. Imagine you had a version of deftem (I'll call it defitem) that inspected the fields in your templates:

  (defitem post
    id     nil
    title  nil
    text   nil
    tags   nil)

  (defitem tag
    id     nil
    text   nil
    post   nil)
defitem would see that post has a relationship with tag and tag has a relationship with post by looking at the names of the fields in each template. Since the post field in tag is singular and the tags field in post in plural, it would know that there is a one-to-many relationship between post and tag. Then defitem could create any necessary accessor methods.

Anyways, that's what I've been attempting recently.

-----

2 points by skenney26 6424 days ago | link | parent | on: Will/Can Arc create a LISP-revival?

Arc seems pretty open to me. There's nothing stopping people from creating countless useful libraries. I'm guessing that many people have turned away from Arc after seeing the dirth of libraries. Paradoxically, that's one of the things that attracts me to Arc. There are many opportunities to make an early impact within the Arc community.

-----

2 points by KirinDave 6424 days ago | link

All of the work in anarki could be invalidated by the next pg arc release. Since pg is the font of arc, there is nothing anyone could say about it.

The community forks arc, but they aren't included.

-----

4 points by skenney26 6425 days ago | link | parent | on: Lispy web development alternatives

I haven't tried it myself but Slava Akhmechet (defmacro.org) created a web framework for Common Lisp called Weblocks (http://common-lisp.net/project/cl-weblocks/).

As far as the lack of a regex library in Arc you could probably make use of PLT MzScheme's built-in support for regular expressions (http://download.plt-scheme.org/doc/mzscheme/mzscheme-Z-H-10....) or the pregexp.ss library (http://download.plt-scheme.org/doc/mzlib/mzlib.html) for Perl-style regex. Anarki allows you to call scheme functions from within arc by using $:

  ($ (sin 1))

-----

3 points by skenney26 6429 days ago | link | parent | on: Macro trouble

If all you want is to add two numbers together, a function will be sufficient:

  (def meta (x y)
    (+ x y))
Macros are usually only used when trying to accomplish something that cant be done with a regular function. If you want to accept an arbitrary number of arguments, the following would work:

  (def meta (x . y)
    (apply + x y))
or:

  (def meta xs
    (apply + xs))
This could also be accomplished with a macro:

  (mac meta xs
    `(+ ,@xs))
In your original definition of meta, arc thinks that y is a list since it follows the dot syntax (x . y) It then throws an error when it evaluates (+ 1 (2)) because it doesn't know how to add a number to a list.

-----

1 point by schtog 6429 days ago | link

i was just playing around with macros figuring out more precisely how they work.

  arc> (mac meta xs
      `(pr ,@xs))
* redefining meta #3(tagged mac #<procedure>) arc> (meta 3 3 4 5 66 67) 334566673

why is this macro returning the first number in the end?

and why is the @ there? leaving it otu gives the same result for the tests i made.

-----

3 points by skenney26 6429 days ago | link

It looks like pr prints out all its arguments and then returns its first argument. You can safely ignore the final value. If pr was used in a web page to print out some text, the return value would never be seen.

As far as the @ symbol, the following code causes an error:

  arc> (mac meta xs
         `(+ ,xs))
  *** redefining meta
  #3(tagged mac #<procedure>)
  arc> (meta 1 2)
  Error: "Function call on inappropriate object 1 (2)"
The comma symbol inserts a value:

  arc> (= y '(1 2 3))
  (1 2 3)
  arc> `(x ,y z)
  (x (1 2 3) z)
,@ inserts a value and removes the outermost pair of parens:

  arc> `(x ,@y z)
  (x 1 2 3 z)

-----

1 point by jmatt 6429 days ago | link

xs will have a type of 'cons in this situation. Which means it sees it as (element . list). So for your example it'll see it as 3 (3 4 5 66 67). It just happens that pr deals with cons types well.

If you wanted to return another value, you could.

  (mac meta xs `(do (pr ,@xs) (last ',xs)))

  arc> (macex '(meta 1 2 3 4 5 6 7))
  ((fn () (pr 1 2 3 4 5 6 7) (last (list 1 2 3 4 5 6 7))))

  arc> (meta 1 2 3 4 5 6 7)
  12345677
Another way to return the last element of fn...

  (mac meta xs `(do (pr ,@xs) ,@xs))
  
  arc> (macex '(meta 1 2 3 4 5 6 7))
  ((fn () (pr 1 2 3 4 5 6 7) 1 2 3 4 5 6 7))
  
  arc> (meta 1 2 3 4 5 6 7)
  12345677

-----

4 points by skenney26 6431 days ago | link | parent | on: Function call on inappropriate object 5

It looks like the final left paren in hyfac is misplaced. It needs to be before the call to fac. Also, unless you explicity return y, hyfac will just return nil.

  (def hyfac (n)
    (let y 1
      (for x 1 (+ n 1)
        (= y (* y (fac n))))
    y))

-----

3 points by skenney26 6432 days ago | link | parent | on: Arc on Windows, trouble installing

To get arc running on Windows I downloaded DrScheme (http://download.plt-scheme.org/drscheme/), which includes MzScheme. After installing DrScheme launch the application. When first using DrScheme the IDE will ask you to select a language in the lower left hand corner. I chose PLT -> Textual (MzScheme, includes R5RS). Then go to File -> Open and navigate to as.scm in your arc directory (it doesn't matter where the arc files are located on your system). Click Run at the top of the IDE and the Arc prompt should start up.

-----

1 point by skenney26 6437 days ago | link | parent | on: Documentation of Arc's web server

Am I correct in thinking that asv only supports one-way asynchronous communication from the client to the server? If so, does anyone have any ideas for supporting two-way async?

-----

2 points by kens 6437 days ago | link

Actually asv doesn't even support that. It has jfnurl* which is called an asynchronous request, but really it's just a normal request with the result thrown away. The client still blocks for the duration of the request, so nothing is really asynchronous. I suspect asynchronous communication is a not-yet-implemented feature.

But to answer your question, it depends what you mean by two-way async. HTTP only supports requests from the client to the server, so you need to use something like polling, Ajax, HTTP server push, or Comet (see http://en.wikipedia.org/wiki/Comet_%28programming%29). I don't think there's anything in srv.arc that would prevent a persistent server connection, if threadlife* is increased from 30 seconds. (A thread per persistent connection would eventually have scaling issued, though, I think.)

-----

3 points by kens 6436 days ago | link

I took a closer look at using Ajax with Arc. It turns out to be pretty easy, thanks to script.aculo.us. I've written details at http://arcfn.com/2008/04/ajax-and-arc.html - please let me know if it works for you or not.

-----

2 points by kens 6434 days ago | link

I've substantially changed my example, so it now fetches country data using Ajax.

The biggest problem with using Ajax is that the Arc web server doesn't support .js files, which is a big oversight for a web-targeted language. Consider this a bug report suggesting support for .js static files. (Really the design should allow arbitrary static files with arbitrary mime-types, rather than hard-coding the list.)

If anyone has Arc running on a public web server and wants to run the Ajax example, let me know and I'll add a link to your site from my page. (My hosting isn't suitable for running Arc.)

-----

1 point by absz 6434 days ago | link

Actually, the Anarki supports exactly what you want with static files: a root directory for static files, and a table mapping extensions to mime types for them.

And there's a typo on your page: you don't close the code tag around "/getcontents?field=population&name=value", so the rest of the page is in monospaced font.

That said, your site is consistently fantastic, and I find it amazingly useful. Please keep it up!

-----

1 point by skenney26 6437 days ago | link

I was referring to Ajax. Thanks for your input (and the great documentation).

-----

More