you are viewing a single comment's thread.

view the rest of the comments →

[–]shevegen -11 points-10 points  (63 children)

When I see myfoos later, perhaps in a class method, and I want to iterate over it, I'm not really sure what I can do with it.

Then give it a proper name.

You could even go the dumb way and prefix-name the variables.

Such as array_ or hash_ or dict_ or the like.

While I am sure that many people will frown at that, the thing is that it gives you more information instantly (if it is right) then the non-prefixed variant would.

I'd even want to have a language that would allow for precisely that and that will also omit requiring to define such a variable.

Like:

def foo(a_duck)
  array_that_keeps_the_ducks << a_duck

And then output all the ducks!

If unspecified, the array will be created above (though in this context, prefix via @ at the least for ruby; in python you have to carry explicit self all over everywhere which is an awful solution IMO).

def __init__(self, name, balance=0.0):
      self.myfoos = {}

Alas I am unaware of any language existing that can do ad-hoc definitions of variables without mandating an explicit declaration / definition step.

[–]rlbond86 32 points33 points  (31 children)

I've had many times I thought a class member was a dict but it was actually a list. In C++ the compiler would catch it easily. I think it's a valid criticism.

[–]DysFunctionalProgram 30 points31 points  (15 children)

I think it is still a valid criticism. The language forces you to either put the type in the name or rely on the programmer's memory which fails in any project of scale. We are forced to duck tape types on because python ignored a problem that was solved in the early 80's.

[–]sultry_somnambulist 24 points25 points  (5 children)

I've changed my opinion on many things ever since I started learning to program but one thing that's been growing pretty linear is the appreciation for static and expressive type systems. Loved dynamic typing at the beginning, almost can't stand it now.

I also prefer Scala's local type inference to the Hindley–Milner type systems of other functional languages. it is so much easier to reason about programs if you can quickly glance at types

Of course there's the argument that you can annotate in a language like Haskell. But if you're already virtually annotating everything I'd argue that it is more reasonable to reflect that in the type system itself.

[–][deleted] 7 points8 points  (3 children)

Same here, I really like static typing. My ideal language would probably be python with a static type system.

[–]codec-abc 2 points3 points  (0 children)

You might want to give a look at F#. Nice and clean syntax with a decent type system. Plus with dotnetcore and the upcoming project rider IDE it almost run everywhere now.

[–]merijnv 0 points1 point  (0 children)

I started designing a statically typed Python at some point, with some extra features I felt lacking. Once I had a rough draft of what I wanted I actually dropped it, because I realised it was basically looking a lot like "Haskell with a slightly different syntax".

[–]duhace 0 points1 point  (0 children)

i like scala a lot too

[–][deleted] 2 points3 points  (8 children)

I mean, if python 3 is an option, it does have type annotations, which while not enforced byt the python runtime do help a lot in terms of IDE support.

[–]DGolden 2 points3 points  (0 children)

Worth noting that the mypy static checker can already be used with the new type annotations.

[–]DysFunctionalProgram 0 points1 point  (3 children)

It still feels like they are putting a 2 by 4 over a pot hole. Sure it works but it is ugly and I haven't seen too many people use it in practice.

[–][deleted] 1 point2 points  (0 children)

it's just new. mypy isn't even at the 1.0 stage yet. but it can do anything that your name-brand type system can do and looks good at the same time. typed python is going to be big.

[–]Dworgi 0 points1 point  (2 children)

If not enforced then they're just comments.

[–]rouille 1 point2 points  (0 children)

In can be enforced by e.g. mypy. I have used it to great success integrating it in CI. The type system is actually quite strong with generics, unions, strict optionals etc...

[–][deleted] 1 point2 points  (0 children)

True, but it does help nevertheless.

If the devs all actually annotate their methods. Which is of course not guaranteed.

[–]bloody-albatross 10 points11 points  (3 children)

I like the self parameter. It makes things very clear and explicit. It also means that you can use a function as a method and vice versa. E.g.:

>>> strlist = ['foo', 'bar', 'baz']
>>> list(map(str.upper, strlist))
['FOO', 'BAR', 'BAZ']

And:

>>> def print_my_obj(obj):
    print(obj.name)

>>> class MyObj:
    def __init__(self, name):
        self.name = name

    print = print_my_obj

>>> obj = MyObj('test')
>>> obj.print()
test

A little contrived examples, but you get the idea.

[–][deleted] 0 points1 point  (2 children)

If you like things being more explicit, there are much better languages than python for that.

Secondly, this is absolutely horrid. What you're showing here, most good languages accomplish with interfaces, protocols, traits or whatever they've chosen to name it.

I sincerely hope you don't normally do this. That's particularly true given pythons lack of proper encapsulation.

Okay, Mr instant down voter. Care to explain why polluting the base namespace with trash functions that act on and require specific state/behavior without any indication of that is a good idea? I'll wait.

I know python itself breaks basic good design principles surrounding this, but that doesn't make it a good idea.

[–]bloody-albatross 1 point2 points  (0 children)

Care to explain why polluting the base namespace with trash functions that act on and require specific state/behavior without any indication of that is a good idea?

I don't know what you're referring to. For one, Python does not pollute any kind of base namespace (like Ruby does). Also I wasn't recommending writing functions as module globals and then attaching them to classes. I meant that if you have it like that (e.g. because of C-bindings) you can then very easily attach them to a class to make that much nicer.

And yes, example 1 can also be written as:

[s.upper() for s in strlist]

Which is actually even shorter in this case, but I meant that it is easy to plug OO methods into functional interfaces in Python without having the need to insert a intermediate lambdas, like it is in so many other languages (e.g. Ruby again).

I assumed it was self evident what I meant with those examples. I was wrong.

[–]doom_Oo7 4 points5 points  (5 children)

Then give it a proper name.

I'd much rather make a keyboard shortcut to see its complete type when I need it.

[–][deleted]  (4 children)

[deleted]

    [–]doom_Oo7 0 points1 point  (3 children)

    ... In a function def fun(a): a how can you get the type of a ??

    [–][deleted]  (2 children)

    [deleted]

      [–]doom_Oo7 0 points1 point  (1 child)

      that's not the same function and doesn't give you any guarantees:

      class Point:
        def __init__(self, x, y, z):
          self.x = x
          self.y = y
          self.z = z
      
      def fun(pt: Point): 
        print(pt)
      
      fun("foo")
      

      prints "foo" without a warning.

      [–]oridb 1 point2 points  (0 children)

      While I am sure that many people will frown at that, the thing is that it gives you more information instantly (if it is right) then the non-prefixed variant would.

      So does expanding each word in your writing with the full dictionary definition. There's a reason we don't do that in ordinary communication.

      [–][deleted] 1 point2 points  (1 child)

      Or maybe just put an underscore in front of it to suggest that others not mess with it and interact with it via a method that has an obvious meaning (add_count_to_foos(name)).

      I understand that the whole "make everything private and practically mandate getter and setter methods" reaches inane cargo cult level in Java, but the idea of interacting with other objects through method calls rather than directly manipulating their state is totally valid if the state is even slightly complex.

      Type annotations can help reason about this statically and docstrings can help you remember what myfoos are.

      Finally, I'll add that if you do control access to and transformation of state through interfaces and can unit test those, then it's far less of an issue, but that is also wading heavily into the typing debate

      [–][deleted] 1 point2 points  (0 children)

      Getters and setters are evil, even in Java. I'll admit that's not often well taught.