Hacker News new | past | comments | ask | show | jobs | submit | tef____'s comments login

design, like engineering is about tradeoffs, and flourishes in the presence of constraints. unlike engineering it is often about the cross-domain trade offs.

it's a nice love note to design, written by someone who has learned more css than information design.

the pie charts are terrible (i'm totally sure he interviewed dieter rams and asked him to put a numerical quantity on the importance of his principles).

I can't see a way anyone can interpret the data accurately from the charts he's written.

the pie charts are misleading, the bar charts use two different proportions of responses (engineers vs 'biz'). the axes aren't labeled properly (is it % is it number of responses).


as much as it says that in a fielding-style rest system the URLs and verbs are opaque, he spends a lot of time nitpicking over the format of urls.

unless the resource in question is exposed as an endpoint, the url and verb are handled by the link or form discovered by the client, and invisible to the client.

as for versioning - versioning the mime types is a useful thing, but it does still make sense to use a different url if you are using different links and forms to navigate the service.


I would have preferred to see an extended read-only period, rather than a month in which to panic-download your data (and the export functionality seems to be broken right now too https://convore.com/export ).

I'd really like it if there was more time to capture the site and submit copy to the internet archive. I'll see what I can do with archive team.

So long, and thanks for all the data! Perhaps convore is an apt name for something that consumes your history. :-)


Export worked for me, but it's moronic. It seems like every user gets all his utterances.. which are utterly useless without context.

They're basically treating the data as if it's email or facebook posts and comments (those last also mostly useless without context). But it's not, it's a far finer granularity of interaction.

Convore, please let users download logs for the channels they're members of.


rest is how the web works.

if you used a browser to write that comment, I would say rest is working pretty well.


From you're massively oversimplified statement I can only conclude you don't understand REST. HTTP != REST. REST is how the architects of HTTP generally expected things to work, but due to tunneling, and other approaches to API design it, generally speaking, most systems that operate over HTTP don't actually work that way.

In fact I'd be willing to bet this comment form isn't all that RESTful.


A language used by beginners is not the same as one designed for beginners.

I would wager that a language designed for beginners wouldn't have so much inconsistency, nor dump the user in a world of security issues with little or no support (XSS, CSRF, SQL injection).

Other people have worked around these issues, but that demonstrates the lack of support within the language.


Agreed, PHP is not beginner friendly even if it might seem so at first.

The lack of built-in XSS prevention in PHP makes it quite terrible as templating language, especially for beginners who probably have never heard of XSS. The same applies to the simplciity of string interpolation combined with the terrible built-in MySQL driver which makes parametrized queries harder than they should be. All this used to be even more confused by the Magic Quotes in previous versions of PHP.

With so many security traps it is not a language I would recommend for beginners who just want to build something that works.


To echo your sentiment, It's a bit like measuring writers not by the books they have written, but how long they've sat in front of a keyboard.

Anecdotally, Not only is time a a poor measure of ability, those who use it as such demonstrate a lack of accomplishment. Compare those who write "N years of Language X" vs "Wrote A,B,C in Z using ...".

I find "I've used X for N years" to mean "I've done one year of X over and over and over" :-)


You've invented your own incompatible dialect of python. You've broken composition, objects and the general design choices of python.

1. You break Composition

Your magic flag within a list changes all the semantics of the methods between immutable and mutable lists.

> x = List([1,2,3]).saving()

So now, if you're passed a list you have no idea if the operations you do will mutate the list.

This breaks composition entirely. You can't pass a mutable list into a function built for immutable lists without destroying things.

2. You break objects

Picking another example, this breaks duck typing and inheritance and polymorphism.

>def user_logged(users): > return List(users).all(User.is_logged)

this does not have the same semantics as:

> def user_logged(users): > return all(user.is_logged() for user)

Because the method lookup is done per instance, rather than assuming everything is the same class.

3. You're writing jquery in python

Python chose not to demand that all iterables implement a series of operators, but provides them as functions within a module. The rationale is that it is easier to add new functions within itertools, and there is far less to do to correctly implement the iterator protocol

You can see this in the "".join(foo) operator too. Instead of demanding all iterables support join, string takes an iterable as argument.

Making readable and maintainable python comes from using the existing idioms within the language and used within the community. Your proposed solution isn't readable, and it isn't pythonic.


What is with all the hate lately on anyone who dares to write Python with different semantics than employed by the stdlib builtins?

'You've invented your own incompatible dialect of python. '

It isn't a "dialect." You don't need a different parser. There are no macros. It is simply a container with slightly different semantics than the stdlib ones.

"You've broken composition, objects and the general design choices of python."

No those all still work and if you don't like his semantics don't use them. They are perfectly readable and easily understandable if you having a passing familiarity with the pattern he is using.

tl;dr : I don't see what the big deal is, people are allowed to write Python however they want.


tl;dr: you didn't read my post. I am pretty sure I made it clear how composition breaks.

'people are allowed to write Python however they want.'

people are encouraged to write python other people understand.


No I did read your post. Actually I read all of them. My point is he didn't "break" composition. In isn't like you import this guy's library and suddenly function composition no longer works. Breaking isn't the right word. It is agressive and wrong on a semantic level.

You could say "You functional list does not properly support composition. Here are some problems." You posts were needlessly combative. I only spoke out because I have seen this kind of thing cropping up recently with respect to Python functional libraries.

"people are encouraged to write python other people understand."

As I said, the semantics of his library are reasonably clear on inspection doubly so if you read the docs.

EDIT:

I just re-read some of your other posts on this thread. You really do keep banging on "He made his own 'dialect.'" To clarify, no he didn't. Making a library isn't a dialect. A dialect needs to be a significant enough departure that you would actually need a different parser/interpreter. That is a "dialect." If you would like I can point you actual Python dialects. This is a library. Deal with it.


"the semantics of his library are reasonably clear on inspection"

does .remove() mutate in place or not ? depends on the constructor!

this would be an example of breaking composition - you can no longer use a function built for an immutable list on a mutable list. I am sure I explained this too.

a dialect is a style, in linguistic terms, if I speak a dialect of english, I still speak english.

if I needed a different parser/interpreter I am pretty sure that is the stage of 'new language' where new syntax and semantics are introduced.

the 'dialect' he is introducing is a arc/clojure inspired syntax for what /already/ exists in python.

thanks for the semantic pedantry! the long and the short of it is that if you want to write python, write python that looks like python. not like scheme or clojure.

as someone who gets paid to maintain shitty code, i'd rather people stuck to the existing idioms of the language, rather than blindly copy paste them from another language.


"if I needed a different parser/interpreter I am pretty sure that is the stage of 'new language' where new syntax and semantics are introduced.

the 'dialect' he is introducing is a arc/clojure inspired syntax for what /already/ exists in python."

No a dialect is another version of the language. For instance python3 is a dialect of python, just as python2 is. They are not 100% compatible.

"as someone who gets paid to maintain shitty code, i'd rather people stuck to the existing idioms of the language, rather than blindly copy paste them from another language."

It is not his problem you see a lot of shitty python. It is also not his problem if you want every one to stay stuck in the poor design choices that were made in the stdlib a long time ago. You can fight evolution of languages or you can embrace them. I don't see you advocating for "thou" in English ;-)

"the 'dialect' he is introducing is a arc/clojure inspired syntax for what /already/ exists in python."

"syntax" --> no thats is what is defined by the grammar of python. This is python syntax.

"a dialect is a style, in linguistic terms, if I speak a dialect of english, I still speak english."

No it is a mutation. But I agree with you if you speak a dialect you still speak the "language." Olde English is still English.

---

However my main point remains. You are needlessly combative in this thread. He made a library you attacked him like he insulted the Pope of Python. I am sorry you maintain shitty Python but you don't need to take you anger about that out on some poor guy on hacker news.


Thanks for the feedback, these are interesting points. I'd like to clarify a couple of things about your #2 and #3.

    def user_logged(users): > return List(users).all(User.is_logged)
    # If you want per instance:
    def user_logged(users): > return List(users).all(lambda x: x.is_logged())
And, about the "".join; you are right. However, Moka's construct allow you to use whatever you want, i.e.:

    moka.List(['a', 'b']).do(string.join, '').last_value
Or, you can still use:

    ''.join(moka.List(['a', 'b']))

However, about the #1, I have to agree. I've added the saving() recently and had a bad taste about it. The right way to do it might be to make it mutable by default and only toggle it off in certain circumstances.

Please note that everything done by the community is still perfectly usable; in fact, it's even easier to use useful high-level functions.

I.e. map(str, range(1,10)) or List(range(1,10)).map(str); is syntactically different but does the same job.


#1 the correct way to do it is to have the methods perform the same action on mutable and immutable objects.

this is the only way to guarantee composition. you do not change the semantics of shared methods.

#2

for both of these examples you give 'to use whatever you want'

"".join(['a','b']) is how everyone else does it in python code.

it isn't about things in the community being usable within your library, it is about your library being /unusable/ within the community. You re-invent new and awkward ways to do standard things without standard idioms.

'i've just invented a whole bunch of new semantics for things so it will be readable'

readability is about /convention/. readable to whom? pushing your own love of jquery method chaining only serves to ostracise those already somewhat knowledgable within python.

it is not pythonic in any way shape of form.


if you are inventing a new way to do existing things outside the idioms of the language there is no conceivable way you can claim to be pythonic.

you are replacing the pythonic style with your own taste.

don't confuse the two.


I'm not sure why you created a fake account to answer this but thanks again for your time. You're right that it was built for my own taste using simultaneously other languages (clojure, arc and js for instance). At the end of the day, what's important is that it increases the quality of the code and this is my goal with Moka. This is still in an alpha stage, but I'll definitely tweak it based on good feedback (Like yours) Feel free to drop me a line: phzbox at gmail if you want to continue this discussion.


It's totally legitimate for you to write this according to your own taste and use it. I don't think it's bad for Python, or anything like that. You are not an idiot and I am sure you can write interesting and useful programs in Python.

But I do agree that it is not 'Pythonic' - except maybe in the trivial sense that it's written in Python.

I would be happy to go into more detail if you really want it.


I'm not sure why you accuse me of having a fake account?

Re-inventing a uniform syntax for python is the least pythonic thing you can do.


give it a break. sure, we should be pythonic when we're programming at work and our code is likely to be maintained by others. but there's absolutely nothing wrong with pushing boundaries and learning by exploring and even - shock - getting things wrong.

you made some good points (particularly the fact that you lose dispatch by instance), but you don't need to keep jabbering away about the same points.


writing your own dialect of the language can be fun, but he is presenting his own style as 'pythonic' as opposed to the actual pythonic style built from functional composition - rather than method chaining.

I am banging on about a lot of the points because it seems very hard to explain to him that using clojure/arc/jquery styles is very very unpythonic.


you seem to go a long way to reinvent python builtins like reverse() any() all() enumerate(), itertools and functors. another python style you violate is that mutable methods return None in general.

from the outset you haven't made any attempt to learn python style. go and read the zen of python.

I only picked on a handful of examples, but wait! theres more - almost every example on your page has a way to do it in python. that other python developers use and understand.

#chaining example:

you say 'we believe chaining constructs are easier to read and maintain than deeply nested expressions.'

zen: flat is better than nested

> Dict(a=1, b=2).update(c=3).rem(lambda x, y: x=='a')

becomes

> d = dict(a=1, b=2)

> d['c'] = 3

> del d['a']

#'partial application' example

> List([1,2,3]).map(string.zfill, 8, _)

becomes

> [str(i).zfill(8) for i in [1,2,3])

# magic argument names

zen: 'explcit is better than implicit'

different methods have different magic attached: it isn't obvious from the outset why update takes named args but keep takes args are named operators

> List([1,2,3]).keep(gt=1)

becomes

> [x for x in [1,2,3] if x > 1]

# you reinvent all

> List(range(1,10)).all(lambda x: x < 100))

becomes

> all(x < 100 for x in range(1,10))

# 'compact' example

> List([None, 0, 2, []]).compact()

becomes

> [x for x in [None, 0 , 2, []] if x]

# 'list is empty' example

> List([]).empty()

becomes

> bool([])

# 'sort'

> List([5,3,1]).sort()

becomes

> sorted([5,3,1])

'uniq'

> List([1,1,2,3,2,1]).uniq().sort()

becomes

> collections.Counter([1,1,2,3,2,1])

for every example you give, there is an equivalent piece of python code to do it, designed in mind with the rest of python. the built in operations give you flexible control over the evaluation too - you can have generator expressions and list expressions. many iterable versions of the standard operators exist in itertools.

really, this is the least pythonic thing since ruby came out. it seems I can only spell this out to you by elaborating through your jquery library and presenting you with python code python developers understand.

please stop re-inventing python without trying to understand why it looks that way first.


Thanks for all the good points. To be honest, I'm not sure what you're trying to say. I've been coding in python for years and Moka was built from my annoyance using functional paradigms with the stdlib.

As you clearly showed, Python doesn't have an uniform syntax to deal with this paradigm. I.e. there are lots of different constructs and, as you said, common idioms or patterns. Have you already argued with a Java programmer saying that these 'Design Pattern' are just a limitation of the language.. whereas in Python you'd probably just use a simple Dict (or whatever)? I'm sure you did. I feel the same with the idioms and patterns.

See, in Clojure (And Arc, and even Ruby), there is an uniform syntax.. whereas in Python we've got itertools, list comprehension, builtins map/filter, random builtins functino such as sorted().

I have to agree with you that Moka is not Pythonic in the There's only one way to solve a problem as we add a new way. However, Moka was created because there was so much inconsistent alternatives..

However, Moka is Pythonic in how it behaves. God knows I could have use all nifty hacks to make it behaves magically.. but I chose to take the explicit route by overriding list/dict. I could have used string interpolation for function (See http://osteele.com/sources/javascript/functional/); but instead went the Pythonic way with standard lambda functions. Maybe you are right about the operator keywords shortcut (i.e. using List().keep(operator.eg) instead of List().keep(eg=); However, I still feel it was a way to make it even easier to integrate with existing tools from the stdlib.

Lastly, you said:

    zen: flat is better than nested
    > Dict(a=1, b=2).update(c=3).rem(lambda x, y: x=='a')
^^^^^^^^^^ This is not nested, this is chained.

This, however, is nested: # Taken directly from the itertools stdlib page. next(islice(iterable, n, None, default)

    # Here, this is not nested.. this is chained:
    def logged_user(self):
        return (self.users
                      .keep(User.is_logged) 
                      .keep(lambda u: u.is_active)
                      .map(lambda x: User.objects.get(id=x)))


so you're admitting you're writing an incompatible dialect of python in python?

that was my point. if you think it is worthwhile, well - enjoy :-)

if you want to write in something with a uniform syntax, use scheme or clojure. python things look different for a reason.


Maybe I don't understand what you mean by "incompatible dialect". These are simple classes inheriting from list/dict. Basically, it simply add a couple methods to these objects. I.e. You can still use all the idioms/patterns; these are list/dict. I'm not creating a new paradigm, or writing a new language by tweaking the syntax. There's really nothing magic going down here. I.e. you can do

    return List(..).update(..).update(..) 
Instead of;

    l = List(...)
    l.update(...)
    l.update(...)
    return l
You can still use lisp comprehension, itertools, etc. In fact, I could pass a moka.List to your existing code and you wouldn't even notice it. (And you do, it's a mistake that I'd fix).

I do agree that I might have been overkill with some useless methods and I'm thinking about removing them. (I.e. such as 'join' as it's really not needed)


Yeah, get rid of saving(). Not only are the semantics dangerous and confusing, but the name suggests the opposite of what it actually does.


''Try/catch is goto wrapped in pretty braces.''

From this I can infer that lambda is also an anti pattern.

But as good as this straw man post is, yes you can mis-use exceptions, No that doesn't make it an anti pattern.


Glad I wasn't the only one thinking of Lambda: The Ultimate GOTO


notably, java 7 uses timsort for the default stable sort (on objects)

and dual pivot quick sort as the default unstable sort.

dual-pivot quicksort is worth a look too, if you enjoy timsort

http://gdtoolbox.com/DualPivotQuicksort.pdf


the approach is used in functional languages too (without galloping)

for example 'run sort' in prolog

http://www.scss.tcd.ie/publications/tech-reports/reports.05/...


Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: