Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

Favorite function

Name: Anonymous 2010-01-10 22:29

printf

Name: Anonymous 2010-01-11 18:52

probly malloc. i'd have to think about it more than i care to.

Name: Anonymous 2010-01-11 19:36

fork()
I like its name.

Name: Anonymous 2010-01-11 20:38

I always really liked pow()

Name: Anonymous 2010-01-11 20:44

cin

Name: Anonymous 2010-01-11 21:40

operator>> and operator>>= because, with overloading, I can almost pretend I'm using Haskell

;_;

Name: Anonymous 2010-01-11 21:51

Mine has to be lambda (or whatever variant of lambda) or bind. Not to be confused with the socket bind function.

Name: Anonymous 2010-01-11 22:10

>>46
implying lambda is a function

Name: Anonymous 2010-01-11 22:32

I like alloca(). It's great for string manipulation, and I don't have to worry about managing memory.

Variable length arrays are a lot better for this since they have proper block scope instead of function scope (e.g. inline a function that uses alloca() into a loop, kaboom), but unfortunately they aren't nearly as widely supported as alloca() (as usual, msvc is the limiting factor).

Name: Anonymous 2010-01-12 4:27

>>46
lambda is a macro.

Name: Anonymous 2010-01-12 5:29

>>49
MACRO MY ANUS

Name: Anonymous 2010-01-12 5:39

lambda is a mobile vagina that outputs anuses

Name: Anonymous 2010-01-12 17:33

>>51
s/anuses/anii/

Name: Anonymous 2010-01-12 18:17

SDL_Joystick_NumBalls

Name: Anonymous 2010-01-12 18:25

Wishful Thinking

Name: Anonymous 2010-01-12 18:58

[code]Leah();{/code]

Name: Anonymous 2010-01-13 5:49

new

Name: Anonymous 2010-01-13 7:06

code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code(code())))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))));

Name: Anonymous 2010-01-14 15:49

>>57

C:\>code
DICKS

C:\>

Name: Anonymous 2010-01-14 15:57

frobnicate

Name: Anonymous 2010-01-14 17:22

foo

Name: Anonymous 2010-01-14 19:06

GOTO

Name: Anonymous 2010-01-14 19:35

>>61
Not a function. goto-like statements/operators almost always translate to a jump in the native language of the platform(such as the machine's assembler or vm's bytecode).

Name: age 2010-01-15 4:51

>>62
I'm sure our compiler implementors, Haskell nomads and SATORI PROGRAMMERS didn't know that. Thank you for your insightful comment.

jump is a function that modifies the program counter, dickass

Name: Anonymous 2010-01-15 4:55

Everything is a function! You know that shit you took this morning, yep, it's a function.

Name: Anonymous 2010-01-15 5:26

Prolog.

Name: Anonymous 2010-01-15 6:03

>>63
It's unusual to implement it as a function in most languages and language implementations. You can make an interpreted CPU emulator which stores the Instruction Pointer/Program Counter in a memory location and have a function which modifies it, but that's how a certain CPU might be implemented(emulated or real, however in real world situations, it's represented as a register), but that doesn't make it a function in the actual bytecode, unless you want to go ignore abstraction barriers and allow your access to the VM memory from within interpreted code (it would make more sense for the code to use a designated jump instruction to change the IP/PC, but of course some "move ip, addr" could work, but it would be counterintuitive, though there is no real difference between "mov ip, addr" and "jmp addr"). If you really wish to argue about silly semantics, you can't really say that a procedure which causes SIDE-EFFECTS on the program counter can be called a function in the mathemathical sense (you would have to specify a different meaning for the word function than is widely understood). I know you could model state in a purely functional way using monads, but that doesn't mean that there is really no state. In reality, everything will be implemented in a purely imperative way after compilation, and ready to be executed by a real CPU which usually works using memory and registers which are inherently stateful. Even if your system is compiled to a VM, that VM would still have state in some form or the other. One should not confuse CPU implementation with the instruction set and its semantics.

tl;dr: goto will almost always be a statement/special operator in real languages(with the exception of languages which don't have goto at all(except in intermediate compilation phases), or those languages with more "powerful" constructs of control-flow transfer).

Name: Anonymous 2010-01-15 11:54

call/cc: the ultimate goto

Name: Anonymous 2010-01-15 12:50

Bew.
This is not really a programing related function.

Name: Anonymous 2010-01-15 12:53

I find that carefully created(by some macro) lambda's can be used to emulate goto quite well and efficiently(if a good compiler is used).

Name: Anonymous 2010-01-15 12:55

>>69
How?

Name: Anonymous 2010-01-15 13:12

Name: Anonymous 2010-01-15 13:18

>>70
It assumes two things about lambda, first that you have access to the environment in which it's defined(it's a closure), and second that the implementation does TCO(it's not necessary, but otherwise things may stack overflow, and the semantics will be different).

I think those that read SICP would have seen this one already:
you can implement loops using tail-recursion, as TCO means that the compiler can optimize those tail calls into simple jumps(with some possible stack unwinding code as necesarry).

Now how do you use this as arbitrary goto?
Let's say you have broken a body with some GO blocks(see common lisp's [m]TAGBODY[m] and GOoperators which is effectively a goto(but it can't do computed gotos!), you could break down everything into code blocks delimited by the tags and then stuff each of these blocks in a lambda form and append a call(jump) to the next lambda: `(lambda () (let ,@body (,next-lambda)), GO forms could be translated to simple (forced) tail-call to the next lambda form thus interconnecting them all and allowing arbitrary jumping between the forms, just like a real GO operator. This also works right since you can access the lexical (and of course dynamic) bindings available in that function, so it can be done fully transparently. It should work both in Scheme and Common Lisp(as long as you're using a decent implementation capable of TCO). Generally, I wouldn't want to use this in CL as it already has a very capable GO special operator for such low-level tasks(useful in control-flow macros), but there is one thing GO/goto can't do that lambda can, and that's computed GOTO (you can tailcall(jump) to any function you like dynamically)!
Usage scenarios could be for example implementing a very efficient case construct based on hashtables or arrays which allows one to use a "jumptable" to jump to the matching piece of code. Most CL implementations seem to strangely implement this naively(the case construct does manual comparisons for each value), while it could be implemented much more efficiently using a jump table. Here's an example of such an implementation: http://paste.lisp.org/display/83487

Name: >>72 2010-01-15 13:32

Here's another reasonable example of using lambda's in this way to implement call/cc: http://common-lisp.net/project/cl-cont/

Name: Anonymous 2010-01-15 14:27

postpone

Name: Anonymous 2010-01-15 14:42

preg_replace_callback

Name: Anonymous 2010-01-15 16:16

>>39
I know right. Everyone has taken a dicking or two in their life.

Name: Anonymous 2010-01-15 17:55

>>73
``CL can do x too, all you need is a global transformation and a reimplementation of all primitives!''

Name: Anonymous 2010-01-15 18:26

>>77
As you can see, it doesn't take that many lines of code, and the effect of the code walker is localized. When I first learned CL I was a bit upset that they didn't tuck in continuations in the standard, given that it does practically support a very large variety of features(just think of CLOS, the type system, arrays, lambda lists, etc which are fairly complex), but now that I know CL decently, and understand its design goals, I can say safely that I'm actually glad they didn't include it. CL tries to include a lot of features, but they make great efforts to make sure you can implement these features in a performant and non-prohibitive way. Supporting continuations natively would have led to various problems:
The way continuations should behave in the presence of some special-operators which deal with the control-flow under exceptional conditions is very hard to define correctly, and you might as well have to make a choice between one of them when defining a language. The issues which can occur in the presence of UNWIND-PROTECT have been discussed and studief in great detail by many Lisers. Dynamic bindings (if present) can cause trouble for a compiler wishing to do TCO in some cases, this could lead to some issues when implementing continuations again (and things like *which* bindings should be used, etc). Implementing continuations naively can be quite an overhead on performance (which goes against CL's goals of making it easy to write implementations which generate performant code), and writing high-performance compilers which implement continuations efficiently is possible, but tricky.

However, one simple way of implementing continuations is recompiling special forms/operators to use CPS and then defining call/cc in that terms is not that hard, and it can be done locally, without penalty to the entire implementation(just local penalty to the code defined in that manner). Besides, CL-CONT(and some other systems which implement continuations and call/cc), aren't that large and hard to implement. In "On Lisp", Graham even gives an implementation for a simple call/cc within a single page of code. His code is mostly fine, except for some slightly abuse of undefined behaviour(which could be easily translated into more proper code... I wonder why didn't he), but it's not an `industrial-strength' call/cc IMO. If you're going to use call/cc as part of some larger system(ex. web based continuations-based frameworks, which allow continuations to persist), you might want to opt for a more global and proper call/cc implementation. Those implementations will of course be larger as they are careful into taking into account the semantics of the entire language and allow your code to interoperate fairly cleanly(as long as you don't use a few conflicting special forms).

If you're curious about the details of some of the technical issues, this paper might be more interesting to you: http://www.nhplace.com/kent/PFAQ/unwind-protect-vs-continuations-original.html

Name: Anonymous 2010-01-15 18:41

However, one simple way of implementing continuations is recompiling special forms/operators to use CPS and then defining call/cc in that terms is not that hard, and it can be done locally, without penalty to the entire implementation(just local penalty to the code defined in that manner)

This is what Marc Feeley talks about in his lecture "The 90 minute scheme to C compiler" although IIRC he just does a full rewrite of everything into CPS. He also suggests that if your code isn't going to be using a lot of continuations it is probably easier and you'd get better performance if you just to copy the stack. Do any of the CL implementations of continuations do the latter?

Name: Anonymous 2010-01-15 19:00

>>79
CL-CONT - portable library, code walker, and implements call/cc via CPS
arnesi - portable library, has a code walker, and implements call/cc via CPS
I also see 2-3 other, less serious, more toyish implementations of call/cc floating around.
One problem with stack copying is that it's not enough: symbols can have their own values, which are stored on the heap. It is possible however to use heap copying: there is a SBCL fork which implements a contrib called SB-HEAPDUMP which does just that and can be used to implement such native persistent closures. I suspect it's doable in some other implementations as well, but I haven't looked into it.

Offtopic: "The 90 minute scheme to C compiler" seems like an interesting experiment I'd like to try. It reminds me of that book "Lisp in Small Pieces" by Queinnec.

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List