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

Complete newfag here

Name: Anonymous 2011-01-13 4:09

Hai, I'm a newfag to C++ and to this board so excuse my giant amount of fail.
Why won't this figure out the smallest thing in the array?
http://codepad.org/vaHOX8mW

Name: >>35 2011-01-13 15:44

Some others:

(defun minimum (numbers) (apply #'min numbers)) ; works only with lists
(defun minimum (numbers) (reduce #'min numbers)) ; works with any sequence

Of course, #'min already performs OP's function, but it accepts a variable number of arguments instead of a list/vector/sequence.

Name: Anonymous 2011-01-13 16:33

Let's post some Lisp macro hackery:
;; simple range macro,
;; builds a list at compile-time when possible.
(define-syntax (range stx)
  (define gen
    (λ (x y s)
      (let-values (((compare +/-)
                    (if (< x y) (values > +)
                        (values < -))))
        (let loop ((x x)
                   (r '()))
          (if (compare x y) (reverse r)
              (loop (+/- x s)
                    (cons x r)))))))
  (syntax-case stx ()
    ((~ n m s) (let ((n1 (syntax->datum #'n))
                     (m1 (syntax->datum #'m))
                     (s1 (syntax->datum #'s)))
                 (cond ((and (number? n1)
                             (number? m1)
                             (number? s1)) #`'#,(gen n1 m1 s1))
                       (else #`(#,gen n m s)))))
    ((~ n m) #'(~ n m 1))
    ((~ m) (let ((m1 (syntax->datum #'m)))
             (if (number? m1) #`'#,(gen 0 (sub1 m1) 1)
                 #`(#,gen 0 (sub1 m) 1))))))

(range 1 10) ; => '(1 2 3 4 5 6 7 8 9 10), built at compile-time
(let ((x 10))
  (range 1 x)) ; same, but at run-time
(range 1 (+ 9 1)) ; run-time, I'm working on this
(range 10) ; => '(0 1 2 3 4 5 6 7 8 9), builds a list of ten ELEMENTS
(range 1 5 0.5) ; => (0 0.5 ... 4.5 5)

Name: >>35 2011-01-13 17:50

>>42
Shouldn't the last case be (1 1.5 ...), unless I misunderstood what the intent of the code was, if given:
1 argument - generate a list from 0 to * given increments/steps of 1, so that you get "first argument" elements.
2 arguments - generate a list from "first argument" to "second argument" given increments/steps of 1
3 arguments - generate a list from "first argument" to "second argument" given increments/steps of "third argument".

Here's my attempt to write this in CL:

(defun seq (start-or-count &optional (end (1- start-or-count) end-present-p)
            (by 1) &aux (start (if end-present-p start-or-count 0))) 
  (loop for i from start to end by by collect i))

(defmacro range (&rest args) 
  (if (every #'constantp args) `(list ,@(apply #'seq args)) `(seq ,@args)))

Difference from your examples is that the third example is ran at compile-time as (+ 9 1) will be detected by my implementation as a constant (most implementations will do this, but they are not required by the standard to do it properly: how well a constant form will be detected depends on your implementation's own optimization code - CL merely gives access to this functionality, but only /recommends/ that compilers perform such optimizations).

Name: >>35 2011-01-13 18:01

And now I realized that a macro isn't really the recommended way to do this (when you have a function and a macro that are supposed to perform the same job, and the only reason you're also writing a macro is for optimization purposes, then you should use a compiler macro), thus the right definition is this:

(defun range (start-or-count &optional (end (1- start-or-count) end-present-p)
              (by 1) &aux (start (if end-present-p start-or-count 0))) 
  (loop for i from start to end by by collect i))

(define-compiler-macro range (&rest args)
  (if (every #'constantp args) `(list ,@(apply #'seq args)) `(seq ,@args)))

The only disadvantage to the macro version is that if you have a braindead implementation, it can refuse to run compiler macros, however if you have a braindead implementation, it might as well decide to not implement constantp for forms like (+ 1 (- 3 2). Either way, almost all major implementations support both of these just fine, so there's really no reason to worry (if you're running an implementation which doesn't support either of those, you've got other problems to worry about than this).

Name: >>44 2011-01-13 18:15

Erm, that's supposed to be
(define-compiler-macro range (&rest args)
  (if (every #'constantp args) `(list ,@(apply #'range args)) `(range ,@args)))

Name: Anonymous 2011-01-13 18:27

>>43
Oh, yes, I wrote that by hand, so I didn't notice, it produces (1 1.5 ... 4.5 5).

constantp
I wish Scheme had constant? too. It's not so difficult to implement, but it's boring and uninteresting.

>>44
Again, Scheme/Racket hasn't compiler macros, so if you have to optimise something (like, in this case, generating a list at compile-time), you have to write a macro.

I'm about to start learning CL, what compiler do you suggest me? Is SBCL a good choice (on Linux)?

Name: Anonymous 2011-01-13 18:44

>>46
SBCL is quite fine on Linux, it is the main implementation that I'm using, however I have my Emacs+SLIME set up so it can load a few other implementations that I have installed, this way I can test/compile my code with other implementations too (as long as I write it portably, if not, I tend to have to write a thin compatibility layer). Other free alternatives worth looking at are ClozureCL (OpenMCL), ECL, CMUCL (SBCL is a fork of this) and maybe CLISP. There's also a handful of decent commercial implementations (AllegroCL, Lisp-Works and Scieneer). If you desire portability to other platforms (Windows, *BSD, OS X, ...), some of those implementations support it (either fully or with some limitations: for example, SBCL's threading is only supported on Linux, however there are unofficial forks which add experimental support for it on other platforms).

Name: Anonymous 2011-02-04 15:45

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