Ruby Programming
 
Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
User Name:
Password:
Remember me
Go Back   Dev Shed ForumsProgramming LanguagesRuby Programming

Reply
Add This Thread To:
  Del.icio.us   Digg   Google   Spurl   Blink   Furl   Simpy   Y! MyWeb 
Thread Tools Search this Thread Rate Thread Display Modes
 
Unread Dev Shed Forums Sponsor:
  #31  
Old March 21st, 2006, 01:54 AM
netytan's Avatar
netytan netytan is offline
Hello World :)
Dev Shed Frequenter (2500 - 2999 posts)
 
Join Date: Mar 2003
Location: Hull, UK
Posts: 2,536 netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level) 
Time spent in forums: 1 Week 2 Days 18 h 3 m 4 sec
Reputation Power: 63
Send a message via ICQ to netytan Send a message via AIM to netytan Send a message via MSN to netytan Send a message via Yahoo to netytan
Most usually closures can be used similarly to instances. What I actually mean by closures are first-class closures. As I think I touched on closures take the opposit aproach to objects and bind the environment to an action – and they don't bind loosly, you can set them up (and I've done this in Scheme) so that changes to the global environment are distant .e. you can change or shadow a function all you like and it won't break your code because it's fully encapsualted.

You can build up an environment and return customized closures for any task from a factory function (Y combinator I believe is the term in maths).

Closures have also been used as the basis for implementing object systems in Lisp for a long time. OO was originally a library before it was included in Common Lisp and it's still a library in Scheme (for now).

You could create a closure over a list or other variables and have it act as a [safe] DB table – in fact this is one area where I think closures are quite common.

These are only the more basic uses of closures, there are a lot of more advanced things that I haven't touched and can't talk about yet .

It should be clear that they're very powerful, and having seemless support for them in a language I'm using to me is very desirable. Here's Daves times example reimplemented in Ruby along with a counter.

Code:
def times(n)
  lambda { |x| x * n }
end

a = times(3)
puts a.call(2)

def make_counter(n)
  lambda do |x|
    n = n + x
  end
end

a = make_counter 1
b = make_counter 0
b.call 1
b.call 1
b.call 2
puts "a: #{a.call 0}; b: #{b.call 0}"


Take care X,

Mark.
Comments on this post
LinuxPenguin agrees: Some nice ideas. I think the refusal to include anything OOP into the core scheme language is one of
the things that holds it back, after all, most programmers will import the oo modules as standard...
__________________
programming language development: www.netytan.com Hula


Reply With Quote
  #32  
Old March 22nd, 2006, 02:58 PM
LinuxPenguin's Avatar
LinuxPenguin LinuxPenguin is offline
fork while true;
Dev Shed God 1st Plane (5500 - 5999 posts)
 
Join Date: May 2005
Location: England, UK
Posts: 5,535 LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)  Folding Points: 11590 Folding Title: Novice Folder
Time spent in forums: 1 Month 3 Weeks 1 Day 19 h 30 m 28 sec
Reputation Power: 1008
I'd just like to take the opportunity to point out that if you don't explicitly return anything, the last statement in a function is returned, thus mark's

Code:
def times(n)
  lambda { |x| x * n }
end


becomes

Code:
def times(n)
  return lambda { |x| x * n }
end


I'm just pointing this out for people who are used to crappy languages like vb which call themselves, but are not, dynamic. This is, in fact the default lisp approach, and possibly why lisp encourages so much recursion

One of the more interesting dynamic things you can do with ruby is writing arbitrary expressions as a string and use the eval() function to call them. It inherited this from perl, where i first found a good use for it.

Here's the line of perl i had to use eval for
perl Code:
Original - perl Code
  1. eval '$sth->execute(' . "'" . (join "', '", @_) . "';


Yes, that looks more undesirable than having your eye stabbed out with a cleaver, but it works, and with good commenting, and occasional line like that can pass. The ruby eval function works the same way, but think of it like this

you can receive arbitrary code from the user and directly execute it within a specific context.

Sounds like closures could be rather useful here, non?

Reply With Quote
  #33  
Old March 22nd, 2006, 07:13 PM
netytan's Avatar
netytan netytan is offline
Hello World :)
Dev Shed Frequenter (2500 - 2999 posts)
 
Join Date: Mar 2003
Location: Hull, UK
Posts: 2,536 netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level) 
Time spent in forums: 1 Week 2 Days 18 h 3 m 4 sec
Reputation Power: 63
Send a message via ICQ to netytan Send a message via AIM to netytan Send a message via MSN to netytan Send a message via Yahoo to netytan
Quote:
Originally Posted by LinuxPenguin
I'd just like to take the opportunity to point out that if you don't explicitly return anything, the last statement in a function is returned, thus mark's

Code:
def times(n)
  lambda { |x| x * n }
end


becomes

Code:
def times(n)
  return lambda { |x| x * n }
end


I'm just pointing this out for people who are used to crappy languages like vb which call themselves, but are not, dynamic. This is, in fact the default lisp approach, and possibly why lisp encourages so much recursion

One of the more interesting dynamic things you can do with ruby is writing arbitrary expressions as a string and use the eval() function to call them. It inherited this from perl, where i first found a good use for it.

Here's the line of perl i had to use eval for
perl Code:
Original - perl Code
  1. eval '$sth->execute(' . "'" . (join "', '", @_) . "';


Yes, that looks more undesirable than having your eye stabbed out with a cleaver, but it works, and with good commenting, and occasional line like that can pass. The ruby eval function works the same way, but think of it like this

you can receive arbitrary code from the user and directly execute it within a specific context.

Sounds like closures could be rather useful here, non?


The function 'eval came from lisp so any language that includes eval did in fact derived it from John McCarthy's original lisp spec .

This includes both Ruby and Python so there's no clear winner here..

The difference between 'eval in lisp and other languages is that you can easily define your own in lisp. As you can imagine this gives you an unparalleled amount of control and is almost a right of passage in scheme .

Writing 'eval in other languages isn't nearly as easy or elegant. This is why something commonly done in lisp is never touched by users of other languages .

To show 'eval the Lisp way here is a little code. 'cons just shoves 'and onto the list of numbers and 'eval evaluates it.

Code:
> (eval (cons 'and '(1 2 3 4 5))) ; evaluate (and 1 2 3 4 5) => 5
5
> 


One important thing that needs to be stressed when using eval for any reason is that you are potentially opening up pandoras box, all you have to do is slip and evaluate some user input and you'll suffer. It's very powerful but should only be used when you can prove its safety .

Code:
> (define unsafe-and
    (lambda (lst) (eval (cons 'and lst))))

> (unsafe-and (read)) ; read asks for user input
< (list (end-universe))
Deleting /
...


You look up and your computer is dead . Obviously you need to be VERY careful when giving users control over such things.

One thing Ruby has over Python here is a notion of safety. Code in Ruby can be executed with different privilege levels, though I haven't read too much about it that certainly sounds like a good idea.

This is something I'm assuming that your using LP? Otherwise doing what your doing isn't the way to go, unless you're programs are to double as all you can eat buffet .

This kind of thing would normally be done with total safety using macros – this is especially true of scheme and it's hygienic macros. Another advantage is that it happens at macro-expansion time (before compile time) so it's very efficient.

OO may well be added to the next scheme standard but that seems to get said before each revision.

I don't think OO is a necessary part of any language. Scheme has a very flexible object system that can be called on when you need it, or extended to suite your task. Why would you want to confine yourself to one way of doing something, in particular why would you confine yourself to the inherent bloat that OO imparts?

As an observation most things can be accomplished much more elegantly, with less code and be just as abstract and modular without OO in the right language .

Night all,

Mark.

Reply With Quote
  #34  
Old March 22nd, 2006, 07:51 PM
SimonGreenhill's Avatar
SimonGreenhill SimonGreenhill is offline
(retired)
Dev Shed God 11th Plane (10000 - 10499 posts)
 
Join Date: Dec 2003
Location: The Laboratory
Posts: 10,101 SimonGreenhill User rank is General 5th Grade (Above 100000 Reputation Level)SimonGreenhill User rank is General 5th Grade (Above 100000 Reputation Level)SimonGreenhill User rank is General 5th Grade (Above 100000 Reputation Level)SimonGreenhill User rank is General 5th Grade (Above 100000 Reputation Level)SimonGreenhill User rank is General 5th Grade (Above 100000 Reputation Level)SimonGreenhill User rank is General 5th Grade (Above 100000 Reputation Level)SimonGreenhill User rank is General 5th Grade (Above 100000 Reputation Level)SimonGreenhill User rank is General 5th Grade (Above 100000 Reputation Level)SimonGreenhill User rank is General 5th Grade (Above 100000 Reputation Level)SimonGreenhill User rank is General 5th Grade (Above 100000 Reputation Level)SimonGreenhill User rank is General 5th Grade (Above 100000 Reputation Level)SimonGreenhill User rank is General 5th Grade (Above 100000 Reputation Level)SimonGreenhill User rank is General 5th Grade (Above 100000 Reputation Level)SimonGreenhill User rank is General 5th Grade (Above 100000 Reputation Level)SimonGreenhill User rank is General 5th Grade (Above 100000 Reputation Level)SimonGreenhill User rank is General 5th Grade (Above 100000 Reputation Level)  Folding Points: 4925 Folding Title: Novice Folder
Time spent in forums: 3 Months 3 Weeks 5 h 49 m 4 sec
Reputation Power: 1331
Facebook
I'm enjoying this discussion folks, & I'm glad to see it hasn't turned into a "my language is cooler than yours" argument, which, lets face it, are entirely pointless ( use the right tool for the job, right? ).

Just a few comments:

Quote:
One important thing that needs to be stressed when using eval for any reason is that you are potentially opening up pandoras box, all you have to do is slip and evaluate some user input and you'll suffer. It's very powerful but should only be used when you can prove its safety


I keep pointing out in the PHP forums that "eval" is just one letter away from "evil", and I've only seen its use justified in a very few cases.

Quote:
in particular why would you confine yourself to the inherent bloat that OO imparts?


I agree here - functional programming is quite under-rated. There are many instances where OOP is just not worth it.

Quote:
Originally Posted by LP
Ruby has always been poorly documented, but it's usually not a problem since i happen to have bought a copy of the pickaxe. The problem, is that the pickaxe doesn't cover thrid party modules (and i don't expect it to).


Documentation is almost always the weak point - I think one of the major reasons that PHP is so successful is that the documentation is fantastic, and other languages really need to look in to doing something similar.

--Simon

Reply With Quote
  #35  
Old March 23rd, 2006, 03:11 AM
netytan's Avatar
netytan netytan is offline
Hello World :)
Dev Shed Frequenter (2500 - 2999 posts)
 
Join Date: Mar 2003
Location: Hull, UK
Posts: 2,536 netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level) 
Time spent in forums: 1 Week 2 Days 18 h 3 m 4 sec
Reputation Power: 63
Send a message via ICQ to netytan Send a message via AIM to netytan Send a message via MSN to netytan Send a message via Yahoo to netytan
Quote:
Originally Posted by SimonGreenhill
I'm enjoying this discussion folks, & I'm glad to see it hasn't turned into a "my language is cooler than yours" argument, which, lets face it, are entirely pointless ( use the right tool for the job, right? ).

Just a few comments:



I keep pointing out in the PHP forums that "eval" is just one letter away from "evil", and I've only seen its use justified in a very few cases.



I agree here - functional programming is quite under-rated. There are many instances where OOP is just not worth it.



Documentation is almost always the weak point - I think one of the major reasons that PHP is so successful is that the documentation is fantastic, and other languages really need to look in to doing something similar.

--Simon


Likewise Simon, too many of this type of thread end up as shouting match's that never get resolved. How could they, it's like religion or philosophy and it comes down to choice. It seems that people really don't like to accept that maybe what they know doesn't place them at the end of some imaginary learning curve – which is probably more like a circle or cubic anyway .

I suppose the thing with 'eval is that (besides the fact that when you try and say it to rhyme with evil it sounds kinda funny) you don't need a lot of people to trip this way to prove this point. It should be pretty obvious anyway but sometimes you need to point people in the right direction, I'm very happy there are people around to point my mistakes out. I nearly made this one once .

When one or two trip with 'eval here they do enough damage to make everyone pay attention, there's something inherently bad about giving users an all access pass to your system.

One of the reasons PHP introduced the $_BLA stuff was because of a nice big security hole, and that's far less obvious .

I have to agree with the documentation and I think this is one of the things that emacs got done right. I'm only a new user but it's self documenting nature is fairly amazing. Without that I'm confident that it would never have been so successful, how do you use or extend an editor you don't know anything about?

Documentation is important, but having a helpful thriving community helps a lot too. Positive feedback anyone. Even with the PHP docs people don't always understand first time.

Both Ruby and Python have a very happy bunch of users (for the most part). That has to be one of the reason these languages are so fun . When you get stuck you all just get around and laugh it out in a friendly manner.

Take care Simon ,

Mark.

Reply With Quote
  #36  
Old March 23rd, 2006, 12:21 PM
netytan's Avatar
netytan netytan is offline
Hello World :)
Dev Shed Frequenter (2500 - 2999 posts)
 
Join Date: Mar 2003
Location: Hull, UK
Posts: 2,536 netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level) 
Time spent in forums: 1 Week 2 Days 18 h 3 m 4 sec
Reputation Power: 63
Send a message via ICQ to netytan Send a message via AIM to netytan Send a message via MSN to netytan Send a message via Yahoo to netytan
I ran out of time this morning but while on the subject of documentation I thought I'd add that Ruby doesn't have docstrings – or it doesn't have them yet .

That puts Python a notch ahead for documentation just there. For those of you not sure what docstrings are they're just documentation embedded at the front of certain forms that you can access interactively.

This is handy when you want to find out how to use a function for instance. With docstrings you can just load the module and read the comments, descriptions and examples etc. that the author may have left for you .

Code:
>>> def double(x):
...     """This function doubles a given number and returns it eg.
...         double(5) => 10"""
...     return x + x
... 
>>>
>>> help(double)

Help on function double in module __main__:

double(x)
    This function doubles a given number and returns it eg.
    double(5) => 10
(END)

>>> print double.__doc__
This function doubles a given number and returns it eg.
            double(5) => 10
>>> 


This is also useful for automatically generating documentation for your code. Something I plan on doing in Scheme over the holidays .

It would be easy enough to put ad-hoc docstrings in any language, all you have to do is parse the language text and collate any comments you find – simple but effective.

Ad-hoc things are never very pretty though so a nice implementation is very valuable!

Functional programming isn't very popular, not many people get it – and many more don't want to get it because they wont get jobs using it. Regardless of that it's a very powerful and well thought out paradigm that will teach you a lot .

If anyone here thinks it's impossible that you could write a program without ever changing a variable then I urge you to check this out . It's not the kind of thing you'd want to do in most popular languages but in those that encourage this style of programming (as Ruby and Python do to a degree) the results can be quite spectacular, I think.

Code:
(define tree?
  (lambda (lst)
    (and (pair? lst) (or (pair? (car lst))
                         (tree? (cdr lst))))))

(define sum
  (lambda (numbers)
    "Adds the numbers in the numbers list and any sub-lists. If numbers is
    a tree? then call sum recursively until there are only simply lists and
    numbers left."
    (apply + (if (tree? numbers)
               (map (lambda (n)
                      (if (pair? n) (sum n) n))
                    numbers)
               numbers))))


Here we go. With a little Scheme you can write a function that will sum a tree of numbers, no matter how deeply nested. All without one assignment or change to the programs state.

Using high order functions you could further generalized it to handle subtraction or any similar function. With a little re-factoring it could also work for other functions – we could call it re-useful because it's both reusable and useful .

The function tree? is cute because it shows a purely logical method of testing if a list is in fact a tree. This isn't inherent to functional programming or Scheme but it provides a nice test bed to see how Python and Ruby handle logical tasks .

Code:
# Python
def tree(lst):
    return bool(lst) and (type(lst.pop()) == list or tree(lst))

print tree([1, 2, 3, 4])
print tree([1, 2, [1, 2, 3], 4])

# Ruby
def tree(lst)
  lst.length > 0 and (lst.pop.class == Array or tree lst)
end

puts tree([1, 2, 3, 4])
puts tree([1, 2, [1, 2, 3], 4])


All of this is important because the quality of your programs depends on your reasoning, and the logic you can express clearly and easily in language X.

Note that this may not be fair example, as I've said I'm new to Ruby and I don't know what methods are available for what . Added to that this is a very simple function.

Also note that bool() is only necessary in the Python version to conform to the original tree? function. You can leave it out if you don't mind getting an empty list .

Enjoy,

Mark.

Reply With Quote
  #37  
Old March 23rd, 2006, 01:44 PM
LinuxPenguin's Avatar
LinuxPenguin LinuxPenguin is offline
fork while true;
Dev Shed God 1st Plane (5500 - 5999 posts)
 
Join Date: May 2005
Location: England, UK
Posts: 5,535 LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)LinuxPenguin User rank is General (90000 - 100000 Reputation Level)  Folding Points: 11590 Folding Title: Novice Folder
Time spent in forums: 1 Month 3 Weeks 1 Day 19 h 30 m 28 sec
Reputation Power: 1008
eval in the wrong hands can quickly go wrong, yes, but in experienced hands, with a large sprinkling of care, it makes the pastry easier to work, but only when it's the only way (as above) (and as you can see, that isn't going to put me at risk)

doc strings are my favourite thing about python for sure, rdoc isn't even close (and python has an equivalent anyway)

PHP's documentation is a great catalyst behind it, and python isn't close behind, just python takes a little more getting used to than php and not as many people program in it (a pity imo, since php is practically useless outside the web - and yes, i know it does other things, but it's only really suited to the web)

lisp is always going to be the master of flexibility

Reply With Quote
  #38  
Old March 23rd, 2006, 02:57 PM
netytan's Avatar
netytan netytan is offline
Hello World :)
Dev Shed Frequenter (2500 - 2999 posts)
 
Join Date: Mar 2003
Location: Hull, UK
Posts: 2,536 netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level) 
Time spent in forums: 1 Week 2 Days 18 h 3 m 4 sec
Reputation Power: 63
Send a message via ICQ to netytan Send a message via AIM to netytan Send a message via MSN to netytan Send a message via Yahoo to netytan
My point was actually that unless you can be prove beyond doubt that 'eval can't be compromised you shouldn't use it. Unfortunately it's very hard to be 100% sure, this is especially true for programs written in imperative languages.

Experienced or not it's probably a bad idea .

If you want to use it go for it, it's certainly very powerful I can't disagree there but I'm just not sure it's worth the risk. I guess it depends on the task .

In general I think if it is to be used it should be used safely behind the scenes, where no user can ever touch it, ever . Alternatively if the language allows it a safe version of 'eval should be used.

I'm sure you know best . What worried me was:

Quote:
Originally Posted by LinuxPenguin
you can receive arbitrary code from the user and directly execute it within a specific context.


I think it would be interesting to see just how much information you could extract form a piece of code i.e. could you reason about the efficiency of a algorithm .

This is the kind of information would be a very useful to include in an documentation because it you could use it to pick the most efficient function/class/whatever for your task. If this is automatic and standard then any code written in language X could be documented easily.

There are some very interesting possibilities there I think .

Have a good day LP,

Mark.

Last edited by netytan : March 23rd, 2006 at 03:00 PM.

Reply With Quote
  #39  
Old March 23rd, 2006, 04:32 PM