Arc Forumnew | comments | leaders | submit | aw's commentslogin
2 points by aw 5776 days ago | link | parent | on: Backward compatability by translation?

I've upgraded my code on every Arc release since arc0, and it's been easy.

This may sound overly simple compared to building a translator, using namespaces or modules, or writing in layered API's, but in practice this is what quickly results in working code for me: in my source code file, I merely arrange my definitions so that definitions that depend on other definitions always appear after the definitions that they depend on.

For example, if h uses g and g uses f, I write out the definitions with the lowest level code appearing in the file first: f, then g, and then h.

(On occasion I'll have mutually recursive functions; those I'll just put next to each other in the source code file. And when I have multiple source code files, I follow the same principle: I ensure that I can order the source code files so that later files depend on code in earlier files, but no earlier files depend on code in later ones).

Now it is simple to upgrade the code in my source code file to a new version of Arc: first I get f to work, then I get g to work, and then I get h to work.

Each step is quick: most often the function doesn't need a changes to work in the new version of Arc, and if a change is needed it's just a tweak.

No massive monolithic all-at-once conversion needed.

And there's no pressure. My code still works with the previous version of Arc that it is running on. So I can convert over to the new version at my leisure. When I'm ready.

Even if someone wrote a translator, I wouldn't use it myself. It would add an extra layer of complexity (if I have a bug, is it in the new version of Arc, or in my code, or in the translator?), and I wouldn't need it.

-----


Using http://awwx.ws/ac,

  (= ac-tnil (ac-scheme tnil))

  (mac ac-predicate (name)
    `(def ,name (x)
       (ac-tnil ((ac-scheme ,(sym (string name "?"))) x))))

  (mac ac-predicates names
    `(do ,@(map (fn (name)
                  `(ac-predicate ,name))
                names)))

  (ac-predicates
   rational complex real integer exact-integer
   exact-nonnegative-integer exact-positive-integer
   inexact-real fixnum? zero? inexact)

  (ac-scheme (xdef numerator numerator))
  (ac-scheme (xdef denominator denominator))
  (ac-scheme (xdef real-part real-part))
  (ac-scheme (xdef imag-part imag-part))


  arc> (inexact-real 4/5)
  nil
  arc> (denominator 3/4)
  4
  arc> (imag-part 3+5i)
  5
See http://docs.plt-scheme.org/reference/numbers.html for documentation.

-----


Updated with a bug fix: my code to work with both Python's byte strings and Unicode strings was doing neither successfully.

In this new version Arc strings are always converted to a Python Unicode string u'...'; I'll probably add a function to generate a Python byte string '...' at some point.

The Python code currently generates ugly Arc strings with every character escaped; I'll fix that when I have some more time.

-----

4 points by aw 5781 days ago | link | parent | on: Q: How to convert decimal to hex?

Built in is (coerce i 'string 16) which will convert a number to a hex string; then you can pad it with zeros yourself.

  (def bytehex (i)
    (if (< i 16) (writec #\0))
    (pr (upcase:coerce i 'string 16)))

  (bytehex 1) prints 01
  (bytehex 242) prints F2
You can leave out the "upcase" to get "f2" instead of "F2".

To get a string, you can use "tostring" with bytehex:

  arc> (tostring (bytehex 1))
  "01"
or else produce a string directly:

  (def 2hex (i)
    (string (if (< i 16) #\0) (coerce i 'string 16)))

  arc> (2hex 1)
  "01"
  arc> (2hex 242)
  "f2"

-----

2 points by aw 5785 days ago | link | parent | on: Contract ssyntax

Very cool. Thank you for this.

What is the difference between minimal and minimum in this context?

One of the things I like about Lisp is that it makes it easy (or at least easier) to write code transformation facilities like this.

I can imagine other code contraction facilities might be possible, giving suggestions of what might be options, even if they weren't correct all the time. I often notice a pattern in my code that I start to write a function or macro to extract, and then discover that it is already available in arc.arc.

-----

1 point by fallintothis 5785 days ago | link

What is the difference between minimal and minimum in this context?

I basically wanted to preempt complaints about

  arc> (sscontract '(no (no (no (f x)))))
  (~no:~f x) ; equivalent to (~f x)
because I didn't bother finding a clean way to compress it. Quasiquotes are a better example. Even though something like

  (mac even (x) `(no (odd ,x)))
would be fine to define as

  (mac even (x) `(~odd ,x))
sscontract is better-safe-than-sorry:

  arc> (sscontract '(mac even (x) `(no (odd ,x))))
  (mac even (x) (quasiquote (no (odd (unquote x)))))
Note that this specific behavior can be changed; see special-cases.arc.

I can imagine other code contraction facilities might be possible

Good guess: that's my next project. ;)

-----

1 point by aw 5787 days ago | link | parent | on: Atdefs - mutual atomicity

MzScheme only uses one CPU, so using atomic doesn't affect performance.

Unless you're wrapping an I/O operation in atomic -- don't do that :-)

-----

1 point by akkartik 5787 days ago | link

I don't use atomic myself. But I find that enabling the back-end thread slows down the UI threads. I've been struggling to create a simple program to illustrate this.

In fact, wrapping parts of my UI threads in atomic actually makes them more responsive[1]. I think it's because instead of getting 200 thread switches with their associated overheads, a single thread runs to 'completion'.

[1] You're right that throughput may go down, though I try to eliminate IO in atomic blocks. But latency is more of a concern to me than not wasting CPU. It's not the end of the world if new data takes a few seconds longer to make it to the index, but a few seconds in the front-end can make or break the user experience.

-----

1 point by aw 5787 days ago | link

Wow, that's interesting!

"vector-set-performance-stats!" in http://docs.plt-scheme.org/reference/runtime.html returns the number of thread context switches that have been performed, so you might try calling that at the beginning and at the end of an UI operation so you can see how many thread switches happened in between.

-----

1 point by akkartik 5786 days ago | link

Thanks for that tip! With its help I was able to figure out that my background thread was just doing a lot more work than I thought.

-----

1 point by aw 5793 days ago | link | parent | on: Bug in atomic when using kill-thread

There shouldn't be a way to interrupt an atomic operation, because then it won't be atomic.

Your elegant solution to make kill-thread atomic is a good one, if the "killed" thread is in fact guaranteed to be terminated instantly... I'll have to look into it to see if I can find out.

-----

1 point by akkartik 5793 days ago | link

There shouldn't be a way to interrupt an atomic operation, because then it won't be atomic.

An interruptable atomic is basically a transaction that can be rolled back. If it gets interrupted nothing is changed. Probably doesn't make sense to run it from anywhere but kill-thread and similar operations.

To restate my original point: reasonable semantics for atomic are that threads inside atomic can't be killed. How to kill long-running atomics is a separate issue, needing a lot more engineering.

-----

1 point by aw 5793 days ago | link

reasonable semantics for atomic are that threads inside atomic can't be killed

We agree.

-----

2 points by aw 5793 days ago | link | parent | on: Bug in atomic when using kill-thread

Not sure if MzScheme's kill-thread is guaranteed to kill a thread "instantly"? If not, then you have a race condition: you schedule a thread to be killed, but it maybe has just enough time to enter an atomic block before it dies.

But you're on the right track though. We actually don't want to kill a thread in the middle of an atomic... in your very first example, (thread:atomic (while t)), it would be a bug if kill-thread did break that loop. The whole point of "atomic" is that the operation completes before other threads see the result.

So the desired behavior is if a thread is "killed" in the middle of an atomic block, it should finish the block (and release the lock in the normal way), and then die.

The MzScheme documentation web site is down at the moment so I can't look now, but if I recall there is some kind of break or signal mechanism in MzScheme that might help.

-----

1 point by elibarzilay 5793 days ago | link

The documentation server is back up.

-----

1 point by akkartik 5793 days ago | link

Still down for me, but from google's cache:

"Terminates the specified thread immediately, or suspends the thread if thd was created with thread/suspend-to-kill." http://74.125.155.132/search?q=cache:kdhjq2ukTtgJ:download.p...

So it seems kill-thread is guaranteed to kill the thread by the time it returns.

-----

1 point by akkartik 5792 days ago | link

Oh, but break-thread is not: "Registers a break with the specified thread." http://docs.plt-scheme.org/reference/threads.html#%28def._%2... "When a break is detected and enabled, the exn:break exception is raised in the thread sometime afterward" http://docs.plt-scheme.org/reference/breakhandler.html

-----

1 point by aw 5794 days ago | link | parent | on: Function overloading

In the Arc server, I moved creating the request object out of 'respond (http://awwx.ws/srv-misc), so that 'respond is now being passed the request object and does the usual Arc srv action to respond to a request: look to see if there is a defop etc. defined for the request path.

Now I can extend respond to implement my own ways of responding to requests: I can easily have my own way of choosing which action to take (I can have http://myserver.com/1234 display the "1234" item page, for example), or implement my own kinds of defop's.

-----

1 point by adm 5794 days ago | link

I see it now. So type based dispatch is just one of the cases where it can be used. Thanks for the explanation. but why rntz says it's less efficient?

-----

1 point by aw 5799 days ago | link | parent | on: The Perl Server: Calling Perl from Arc

Updated:

- Now trying out using “...” as the syntax for templates.

- Rewrote the section on why I chose the interface I did, added an explanation of why I'm not using RPC, and included a link to andreyf's "The Black Box disease" posting. (http://andreyf.tumblr.com/post/321371513/the-black-box-disea...)

-----

2 points by rocketnia 5797 days ago | link

Curved quotes (“...”) bug me a little because of the way tools like Microsoft Word and Wordpress automagically curve people's quotation marks either as they type or as they publish. Usually, this would just result in a flagrant syntax error, but with your syntax it would have a slightly more subtle effect.

I almost didn't care to mention it. After all, if people are going to compose/publish code in places where prose is expected, they'll get bitten one way or another. For instance, really strange characters might be displayed as question marks, or a random ":o" might turn into an emoticon. But I was amused to find a curved quote code mishap within a day, just by accident: http://www.flashcoder.net/blog/?p=100

  The quotes you use in the MediaControlEvent package result in a
  syntax error in Flash if I copy from browser to Flash.
  
  Rather than:
  “headControl”
  
  should be:
  “headControl”
Automagic curved quotes on a coding blog. Priceless. (I'm one to speak. I think my blog has the same problem.)

-----

More