LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Programming tools and languages for a programmer (https://www.linuxquestions.org/questions/programming-9/programming-tools-and-languages-for-a-programmer-683107/)

acerimusdux 11-27-2008 01:32 PM

Jeepers, you perl guys make things so complicated...

Code:

from functools import partial

def sub(x,y,z):
  ans=(x*y)+z
  print x,y,z,ans

for X in [1,2]:
  FX=partial(sub,x=X)
  for Y in [3,4]:
    FY=partial(FX,y=Y)
    for Z in [5,6]:
      FY(z=Z)


cheers :)

Sergei Steshenko 11-27-2008 01:35 PM

Quote:

Originally Posted by ghostdog74 (Post 3356625)
i don't study CS, nor am i a programmer like you do. alot of what i do are procedural. If you are interested to see how it can be done in Python, post your code to comp.lang.python.

I am not a programmer by education.

And a lot of what I do is procedural too. But I did come to functional stuff from practice - things become more concise and better modularized. And IMO so much advertised OO comes as a subset of functional and functional looks more natural to me.

Interestingly enough, there are languages in which not only functions are first class "citizens", but also types: http://www.aldor.org/ :

Quote:

In Aldor, types and functions are first class values that can be constructed and manipulated within programs. Pervasive support for dependent types allows static checking of dynamic objects. What does this mean for a normal user? Aldor solves many difficulties encountered in widely-used object-oriented programming languages. It allows programs to use a natural style, combining the more attractive and powerful properties of functional, object-oriented and aspect-oriented styles.
And if a language is not functional - it isn't.

The funny thing WRT C++ is that the language itself is imperative (procedural), but its template engine is functional.

Sergei Steshenko 11-27-2008 01:39 PM

Quote:

Originally Posted by acerimusdux (Post 3356983)
Jeepers, you perl guys make things so complicated...

Code:

from functools import partial

def sub(x,y,z):
  ans=(x*y)+z
  print x,y,z,ans

for X in [1,2]:
  FX=partial(sub,x=X)
  for Y in [3,4]:
    FY=partial(FX,y=Y)
    for Z in [5,6]:
      FY(z=Z)


cheers :)

It depends - in my code I call each time the function with one argument, ou - with two, and with an "assignment" - like "x=X".

Furthermore, you have "from functools import partial" which Perl code doesn't have.

So, where is the complexity in Perl code vs simplicity in Python code ?

acerimusdux 11-27-2008 02:10 PM

Quote:

Originally Posted by Sergei Steshenko (Post 3356992)
So, where is the complexity in Perl code vs simplicity in Python code ?

Well, your criteria for judging here were supposed to be:

Quote:

Ability to do more with less effort from programmer.
and:

Quote:

Again and again, write as close as possible the same thing in Python, and we'll discuss maintainability.
So lets discuss. Which requires less effort from the programmer? Which is more easily maintained?

Rewriting the entire function itself in order to accommodate partial callings? Or writing this fairly trivial function as it would be called normally, and then calling it from "partial" when partial execution is needed?

Not to mention calling it explicitly identifying the parameter you desire to set, rather than having to "shift" through the parameters. Someone else coming along after the fact trying to understand and maintain this code is going to see more clearly what is going on in my example, as opposed to having to calculate what is going on in that function with all those shifts.

acerimusdux 11-27-2008 02:37 PM

BTW, I could have done:

Code:

for X in [1,2]:
  sub=partial(sub,x=X)
  for Y in [3,4]:
    sub=partial(sub,y=Y)
    for Z in [5,6]:
      sub(z=Z)

if that makes it a bit clearer.

A good resource for info on functional programming in Python is here:

http://www.amk.ca/python/writing/functional

Sergei Steshenko 11-27-2008 04:04 PM

Quote:

Originally Posted by acerimusdux (Post 3357011)
Well, your criteria for judging here were supposed to be:



and:



So lets discuss. Which requires less effort from the programmer? Which is more easily maintained?

Rewriting the entire function itself in order to accommodate partial callings? Or writing this fairly trivial function as it would be called normally, and then calling it from "partial" when partial execution is needed?

Not to mention calling it explicitly identifying the parameter you desire to set, rather than having to "shift" through the parameters. Someone else coming along after the fact trying to understand and maintain this code is going to see more clearly what is going on in my example, as opposed to having to calculate what is going on in that function with all those shifts.

'shift' is a matter of choice. I could have written $result *= $_[0] for example - thus explicitly pointing to the 0-th (and only in my case) argument.

Someone else coming along, if he/she knows the AST I'm talking about, which is:

Code:

  +
  /\
  *
  /\

perfectly understands what it's about.

In the tree there is no named parameters, there is a path to walk, and I have expressed the path.

You didn't answer my question asked using the example with two "C" functions I've written - one of them calculating a * b + c, the other - x * y + z - my Perl code does not pose such a question, and it's good IMO since the question is irrelevant, your Python code does pose such a question.

If you have to modify the code to become (x * y + z) * u, you'll have to introduce an extra 'u' variable, which is in the same scope as already existing 'x', 'y', 'z', i.e. you have to make sure your newly introduced 'u' entity does not clash with the existing ones.

This, of course, is not a big deal with such a small example, but it becomes a problem in real life - look at futile attempts to use namespaces/packages in C++, Java and even Perl itself if we stick to "traditional" OOP.

"My" approach/code does not have this name collision problem _by construction_, i.e. the only name used ($result) is scoped and export/import is implemented anonymously, thus avoiding the problem altogether.

The last, but not least. Your code is not Python as such - it's Python plus an external module. My code is pure Perl, i.e. I've used only the language.

ghostdog74 11-27-2008 08:14 PM

Quote:

Originally Posted by acerimusdux (Post 3357030)
Code:

for X in [1,2]:
  sub=partial(sub,x=X)
  for Y in [3,4]:
    sub=partial(sub,y=Y)
    for Z in [5,6]:
      sub(z=Z)


thanks for the code snippet.

ghostdog74 11-27-2008 08:21 PM

Quote:

Originally Posted by Sergei Steshenko (Post 3357106)
The last, but not least. Your code is not Python as such - it's Python plus an external module. My code is pure Perl, i.e. I've used only the language.

that's what makes Python just as "powerful", isn't it. for people doing functional programming, its a useful module. why would they try to re-invent the wheel? Moreover functools is included in Python distribution itself.

Sergei Steshenko 11-28-2008 01:48 AM

Quote:

Originally Posted by ghostdog74 (Post 3357259)
that's what makes Python just as "powerful", isn't it. for people doing functional programming, its a useful module. why would they try to re-invent the wheel? Moreover functools is included in Python distribution itself.

No it isn't. It's like having a class for vector or hash table in C++ does not make it part of the language itself.

But, of course, presence of such a module is useful.

I do not know Python 'functools' implementation details, i.e. whether it poses performance penalty or not.

And, at all, it was claimed that Python is a more modern language than Perl - I do not see a proof yet, and I haven't seen the definition of "modern".

Sergei Steshenko 11-28-2008 02:00 AM

Let's check whether Python can do this (this is Perl):

Code:

my %hash;
${$hash{foo}{bar}{doo}{dah}}[3][5] = 'boo';

, i.e. I'm checking autovivification of references existence in Python.

And more :-).

ghostdog74 11-28-2008 02:19 AM

Quote:

Originally Posted by Sergei Steshenko (Post 3357472)
No it isn't. It's like having a class for vector or hash table in C++ does not make it part of the language itself.

well, that's where we interpret the meaning of "powerful" differently, doesn't it.? :)

Quote:

I do not know Python 'functools' implementation details, i.e. whether it poses performance penalty or not.
that's why, there's no point "arguing" whether language X is better than language Y when all one knows is only 1 language and not the other.

Quote:

And, at all, it was claimed that Python is a more modern language than Perl - I do not see a proof yet, and I haven't seen the definition of "modern".
where have you seen or heard that Python is more modern ? What is that definition of "modern" ?

ghostdog74 11-28-2008 02:35 AM

Quote:

Originally Posted by Sergei Steshenko (Post 3357483)
Let's check whether Python can do this (this is Perl):

Code:

my %hash;
${$hash{foo}{bar}{doo}{dah}}[3][5] = 'boo';

, i.e. I'm checking autovivification of references existence in Python.

And more :-).

i think we should not go too deep into this because its becoming OT. If you know more of Python, you would know that setdefault() or the recent defaultdict() can be used to do the above.

burschik 11-28-2008 03:35 AM

Well, my information that Python did not support partial evaluation was apparently out of date. Still, I will venture another opinion, namely that Python does not support autovivification and that setdefault is something else entirely.

Sergei Steshenko 11-28-2008 04:13 AM

Quote:

Originally Posted by ghostdog74 (Post 3357513)
i think we should not go too deep into this because its becoming OT. If you know more of Python, you would know that setdefault() or the recent defaultdict() can be used to do the above.

I don't know Python, but the bold "recent" makes me wonder how modern Python is.

Another unanswered piece - multidimensional array in my example - the "[3][5]" part.

What about multidimensional arrays in Python nowadays ?

And, after quick looking into http://python.net/crew/mwh/hacks/setdefault.html , it's not clear to me how many times I'll have to write 'setdefault' in case of my

Code:

${$hash{foo}{bar}{doo}{dah}}[3][5] = 'boo';
- could anyone please elaborate ?

If the "[3][5]" part is a problem, then

Code:

$hash{foo}{bar}{doo}{dah} = 'doh';
would suffice.

ghostdog74 11-28-2008 04:25 AM

Quote:

Originally Posted by burschik (Post 3357555)
Python does not support autovivification and that setdefault is something else entirely.

with Python 2.5
Code:

>>> d = dict()
>>> d['foo']['bar']=99
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'foo'
>>> from collections import defaultdict
>>> d = defaultdict(dict)
>>> d['foo']['bar']=99
>>> d
defaultdict(<type 'dict'>, {'foo': {'bar': 99}})

or for "nested" dictionaries
Code:

>>> class default_dict(dict):
...  def __missing__(self, key):
...  self[key] = value = self.__class__()
...  return value
...
>>> d = default_dict()
>>> d['foo']['bar']['doo']['dah'] = 777
>>> d
{'foo': {'bar': {'doo': {'dah': 777}}}}


i think it also can be done using setdefault albeit a bit more effort, or does it?

Code:

>>> class auto_dict(dict):
...  def __getitem__(self, key):
...  return self.setdefault(key, self.__class__())
...
>>> d = auto_dict()
>>> d["foo"]["bar"]["baz"] = 42
>>> d
{'foo': {'bar': {'baz': 42}}}

Reference: here


All times are GMT -5. The time now is 06:43 AM.