> though in this case the easy and correct thing for the interviewer to do is to say "OK, how is Collections.shuffle implemented?"
And very likely that's what really happened. I have been in such interviews and it is sometimes hard to guess whether the interviewer wants the practical answer (calling a library function) from engineering standpoint or the conceptual answer (demonstrating that I can implement the inner workings of the function) from CS standpoint. Often I would just ask a follow up question to clarify exactly at which level of abstraction does the interviewer want my solution to be in?
In situations where I offer a solution that does not match the interviewer's expectation, they clarify the expectations.
I think it's stupid to assume that a decision regarding time complexity would never come up at their job. Where I work right now, and especially in Google (not where I work right now), it is important that one understands time and space complexity issues well. The data sizes are huge and optimization skills are highly valued.
Sure I can teach constant vs. linear time. But what incentive or reason do I have to spend time teaching these fundamental concepts when I can just hire an engineer who demonstrates the understanding of basic CS at the interview time itself?
Given two candidates with all things equal except that one demonstrates the understanding of CS fundamentals and other does not, why would I want to hire the second person and spend our time teaching him those concepts?
>why would I want to hire the second person and ...
Someone commented on here recently that they would take motivated candidates over knowledgeable candidates. That's one reason. I can easily think of at least two others.
There are balance points here that vary according to all sorts of things.
I said, "Given two candidates with all things equal except ..."
I mean if there are two candidates who are equally motivated and are more or less equal in all things except that one is strong at CS fundamentals and another isn't, is there a good reason to reject the candidate who is good at CS fundamentals.
In many hiring decisions, I am faced with a similar choice, and I go for the person who is good at CS fundamentals. If two candidates are good in all other ways, then the understanding of CS fundamentals becomes a tie breaker. I see no rationale for selecting the guy who does not demonstrate his strength in CS fundamentals.
I come across candidate A who shows up on time, with a good attitude, takes heat and shares credit, builds people up, isn't afraid to speak their mind and offers a smart-ass answer to a problem designed to evaluate whether the candidate understands the underlying concepts.
Then I come across candidate B who shosw up on time, with a good attitude, takes heat and shares credit, builds people up, isn't afraid to speak their mind and offers a genuine and insightful answer to a problem designed to evaluate whether the candidate understands the underlying concepts.
And where did they give a "smart-ass answer"? A question was asked, an answer was provided. Does the answer solve the problem? Yes. If you want to know more then ask. If you want to hear something else that's a failure of the interviewer, not the interviewee.
> On some Python 3 distributions, you may need to replace pip with pip3 in the command above.
Are there any distributions where the command pip just works with Python 3?
In every Python 3 installation I have used, I had to invoke it as pip3. So it seems to me that pip3 is the commonly used command and one may need to replace pip3 with pip only on some distributions.
AFAIK you usually have pip (system default python), pip2 (corresponds to python2), and pip3 (corresponds to python3). Like others have mentioned, a few distributions have python 3 as the default python.
In later versions you can invoke pip using python -m pip install ..., which makes it more clear which python is being used.
Try `PYTHON -m MODULE` as in `python3 -m pip` if you want to make sure to use python3's pip, `python2 -m pip` for python2, `~/bin/python -m pip` for a personal python install, etc.
I am aware of that. So has been many other distributions like Debian, Ubuntu, etc.
My point was: Which command do you normally use to install packages in Python 3? pip3 or pip?
I thought it was pip3 but the article seems to imply that using the pip command to install packages in Python 3 is common too. If this is true, which distribution ships Python 3 with pip instead of pip3 for installing packages in Python 3? Does it not conflict with pip of Python 2?
$ python2 -m pip ... # If you want to be sure is using Python 2
$ python3 -m pip ... # Use Python 3
$ python3 -m venv ... # Create a virtualenv with Python 3 as documented on https://docs.python.org/3/library/venv.html to "prevent any potential confusion as to which Python interpreter a virtual environment will be based on"
I know it's verbose and long to type but looks explicit to me and saved me to use the wrong version of Python several times.
Ah! That makes a lot of sense. If Python 3 is the default, it does make sense 'pip' to be the Python 3 pip. That way 'pip' always refers to the default version.
Unfortunately in the Ubuntu and Mac world 'python' is still Python 2.7 and 'pip' refers to the Python 2 pip. Python 3 is available as 'python3' along with 'pip3'.
> In that case, it sounds like very bad general software design that is not well-crafted to the problems you are solving.
That does not sound like bad software to me at all. It is quite a stretch to say that types changing during the course of software development implies the software is badly designed. This sound very backwards.
On the other hand, I believe a software that is malleable enough to handle changing types easily during the course of software development is good software.
> “That does not sound like bad software to me at all. It is quite a stretch to say that types changing during the course of software development implies the software is badly designed. This sound very backwards.”
But nobody said that. The parent comment said the system has a requirement to deal with changing types. OK. Sure. Happens all the time.
Solving it by using auto all over and rotating header files, now that is the part that is simply indefensibly bad. It leaves a codebase where nobody can reason locally about any types, because they would be compile-time dependent on which headers you choose, which is insane. Accidentally make one local variable non-auto by annotating a specific type, and suddenly it works with one set of headers but fails indecipherably with a different set.
There are many better approaches, like inheritance-based designs for specialized subtypes, or using discriminated union types and multiple dispatch patterns.
You’re acting as if the parent comment was just talking about mundane refactoring of types here or there, or some small changing requirement, but it’s not at all.
It’s talking about some kind of problem where the commenter claims that huge amounts of types tracing throughout the whole project have to change wholesale by rotating in different headers and relying on auto as essentially a kludge version of whole-program polymorphism.
> “On the other hand, I believe a software that is malleable enough to handle changing types easily during the course of software development is good software.”
I believe that too, which is why this kind of system that relies on the whole codebase having no localized type annotations (so you can’t reason locally about code when you go to refactor or change types, etc.), is so egregiously bad. Making it robust to type changes is a property of how well other developers can modify the code itself and reason about it. Using auto dogmatically like that totally strips away someone else’s ability to do that.
> Solving it by using auto all over and rotating header files, now that is the part that is simply indefensibly bad. It leaves a codebase where nobody can reason locally about any types, because they would be compile-time dependent on which headers you choose, which is insane.
The software I work on performs sometimes up to ~25% better with flat_hash_map - some projects I worked on (as an user of the software) would simply not have been feasible without it or a similar container. Would you seriously consider replacing your map implementation with a variant, or worse, inheritance which forces you to heap allocate and have an additional indirection ? That would be literal madness here, where I'm fighting to make a tick function run in 15 microseconds instead of 20.
The theoretically cleanest solution would of course be to make the whole codebase generic on Map_T. I hope that you see why this is not optimal in C++ when you have ~100 unit test executables - each test will literally need to recompile the whole stuff.
> Accidentally make one local variable non-auto by annotating a specific type, and suddenly it works with one set of headers but fails indecipherably with a different set.
Except it does not because the types conform to the same concepts.
> this kind of system that relies on the whole codebase having no localized type annotations (so you can’t reason locally about code when you go to refactor or change types, etc.), is so egregiously bad.
Nobody said that either. The parent comment specifically said that they have alternate types to provide different performance characteristics and behavior. Such code bases do exist contrary to what you believe.
Don't think of it as an Apple type suddenly replaced with an Orange type on one fine day and your head begins to spin when you try to understand what the code does.
Think of it more like int32_t being replaced with int_fast32_t because you realize you want to port the code to a new architecture due to which int_fast32_t makes more sense now. Now the argument should not appear as "egregiously bad" as you make it look like.
The world of software development is far more heterogeneous than what your experience might have led you to believe.
My particular cases are with various implementations of hash maps and ordered maps that I switch, for instance std::{unordered_,}map, boost::flat_map, pubby::flat_map, tsl::hopscotch_map, ska::flat_hash_map, and a few others.
It’s funny to hear someone say it is “very rigid beliefs” to disagree with dogmatically using auto everywhere just to get polymorphism by swapping header files, which is a far more drastic and brittle belief.
I have worked on systems deploying to embedded devices, so I am familiar with e.g. needing to suddenly change a bunch of code to cause some typedef to refer to int16 because a platform doesn’t support int32, and needing the codebase to be robust to the change. Whatever solution you pick, sacrificing localized explicit type info is not a good trade-off, and ability to read code and locally easily reason about types only gets more critical as the application gets more architecture or performance dependent.
Besides, many systems that need to achieve this same effect do so by either using discriminated union (std::variant) and multiple dispatch patterns, or by designing the different specific subtypes to fit into an inheritance hierarchy, so that switching things to use e.g. different integer precisions is a matter of using a different, specialized subtype. Forcing the use of auto everywhere and switching types by header files would be a nuclear option by comparison.
> ability to read code and locally easily reason about types only gets more critical as the application gets more architecture or performance dependent
Exactly! And using auto for variables with very limited scope where the type is obvious effortlessly does not negatively affect the ability to read code and in my opinion improves the ability to read code.
The usage of the word "strictly" here is strictly sloppy.
Why is a typedef/typename better than using auto in this case? You can literally look up the actual type the auto keyword is deducing by looking at the function parameters two lines above.
How many new typedefs do you want to create for code like this? You are suggesting creating two typedefs for this tiny 4-line code only. Imagine how many typedefs you might need to create in a real and complex project. How is the mess of typedefs going to be any more maintainable than this?
There are places where the auto keyword would make it hard to understand the type and there are places where it won't. This is a place where the auto keyword does not make it hard to understand the type.
Don't use the auto keyword if you don't want to but pretending that there is no value in using the auto keyword by using weasel words such as "strictly" is disingenuous.
> “Why is a typedef/typename better than using auto in this case? You can literally look up the actual type the auto keyword is deducing by looking at the function parameters two lines above.”
Because a typedef makes the syntax equally as short as auto in all practical senses, while keeping the item type explicit. Even when figuring out the item type only requires looking up a few lines, this limitation of auto is still worse while not providing any “terseness” advantage. And obviously ising auto as a kludge for a type of polynorphism where you switch around header files, etc., to arrange the upstream type to change and rely on other code’s use of auto to “just work” is a severe and critically flawed kind of anti-pattern.
In most cases it won’t be anywhere near this easy anyway, the the type of the function parameter should already have had an application-specific typedef to understand its meaning, so the extra use in places where auto is used would amortize it further.
And since you get much more benefit from the typedef way in more complex situations, it would be better style to just use it consistently by using it in simpler situationd too, especially since when the situation is simple, like this example, auto by definition doesn’t provide an advantage.
This is why I specifically used the word “strictly” like the mathematical sense of strictly increasing or a dominated function. The typedef approach for this is superior unilaterally.
> In most cases it won’t be anywhere near this easy anyway
Then don't use auto in such cases -- is the point of the discussion here.
Use auto anywhere it is indeed nearly this easy.
When the situation is simple, auto clearly provides an advantage of automatically deducing types that are very obvious to humans and the compiler. The argument here is that not having explicit types here is better.
Your cannot use the word "strictly" here in the mathematical sense at all since you have not mathematically established that explicit types for simple cases are better. It is only your subjective opinion that explicit types are better even in simple cases and such an opinion is far from the exactness and axiomatic nature of mathematics.
You pretend as if the proposition that "explicit types are better" is an axiom. It is not. To many of us such proposition is neither self-evident nor obvious because many of us believe removing explicit types for simple cases is better. As such, the usage of "strictly" here is merely a weasel word.
> “When the situation is simple, auto clearly provides an advantage of automatically deducing types that are very obvious to humans and the compiler. The argument here is that not having explicit types here is better”
That’s not an argument for anything. It amounts to just saying “worse is better” because you have a preference for how it looks with auto, even though being explicit with the type information is not about you.
There’s absolutely no sense in which less explicit information is somehow better for code readers. The only reason you might choose to pay the cost of having less explicit type info is if it gives you some other benefit, like shortening syntax.
But since typedef/typename offer that too, without the loss of being explicit, it just means auto would be a suboptimal choice even in the shorter/simpler case too.
> There’s absolutely no sense in which less explicit information is somehow better for code readers.
This is patently false. It has been demonstrated more than once in this thread that there clearly are cases where the types can be deduced effortlessly and avoiding explicit information leads to cleaner code.
Your claim is only your subjective opinion/belief and definitely not a fact.
We might just have to agree to disagree, but I would disagree with your claim here in the strongest possible terms. Constantly pretending as if your subjective beliefs comes off as obtuse and is in poor taste. There is one size fits all standard for coding. You are free to follow your coding standards and so is everyone else. What looks like an obvious argument to you may appear absurd to another. Like I said, the world of software development is far more heterogenous that you seem to believe it is.
> “It has been demonstrated several times in this thread that there clearly are cases where the types can be deduced effortlessly and avoiding explicit information leads to cleaner code.”
I do not see a single example in this thread that demonstrates that. Absence of explicit type info is an inherently bad thing. It’s never good to offer code readers less explicit / more ambiguous info.
Like I said, you’d expect some offsetting benefit (what you call “cleaner code”) to compensate for paying the penalty of giving up valuable explicit info. But auto does not actually provide that in comparison to typedef/typename. auto, by comparison, is not meaningfully cleaner code. It only loses valuable explicit information, without an offsetting benefit that couldn’t otherwise be obtained without losing that valuable explicit information.
> Absence of explicit type info is an inherently bad thing.
Let me reiterate: It is your opinion which many people here do not agree with in the context of types obvious from context. Your opinion is definitely not a popular coding standard and definitely not a fact. Most of the coding standards are in favor of using auto for simple code where the type is immediately obvious from the context.
The auto keyword is available to help people who do not share your opinion. The auto keyword is present for teams which agree that absence of explicit type info is a good thing for simple code with obvious types (obvious from the context).
Teams that believe that absence of explicit type info is an inherently bad thing don't have to use the auto keyword. But that belief does not become a fact no matter how many times you reiterate that belief.
> paying the penalty of giving up valuable explicit info
That's your opinion. My opinion which many coding standards agree with: There is no penalty in giving up explicit type info in a local loop variable. The typo info is not valuable in that case.
In my comments my goal was to describe why those other beliefs about auto are just fundamentally mistaken. To lobby for a certain way to think of it.
My perspective on this actually is a very popular coding standard in some communities. For example, in The Zen of Python [0] (which is an official Python PEP) there is, “Explicit is better than implicit” right in the second line. It’s quite a widely regarded principle in programming.
Still, given that I only lobbied to persuade that my perspective is the right one in this case, and did not ever try to claim that people cannot have a different opinion, your comment seems unrelated to earlier part of the discussion.
We also need to think a little about how the times were. Sourceforge rose to popularity in the early 2000s. Free and open source software (FOSS) was not just a matter of pragmatism or convenience. It was an ideology, a philosophy, and a movement strongly pushed forward by FSF, Open Source Initiative, various LUGs, and various special interest groups. Open source enthusiasts used to have very active and influential LUGs all throughout the world. There used to be free and open source software conferences all over the world with the sole agenda of increasing open source awareness among the general public.
In those years, most of the developers who chose to host their projects on Sourceforge strongly believed in this ideology. GPLv2 was the most popular open source license then. Given all this, it makes sense that those early users who held freedom of software to be sacred were very pissed when Sourceforge decided to bundle closed source adware into the binaries of these open source projects without the explicit permission of these open source developers.
Times have changed a lot since then. GPLv2/v3 license is now considered too restrictive and the MIT license is more popular. Most of the tech community understands the concept of open source more or less. The movement in favor of software freedom has begun to lose momentum. Open source software makes a lot of business sense, so we don't need the push for open source software anymore like we used to in the early 2000s.
Even some people like me who once would run nothing but completely free operating system with free tools have now begun to use proprietary drivers because as we have grown older, got busy, with kids and family, the time spent tinkering with open source drivers is not worth it, we would rather use something that just works. When we use Microsoft and Facebook we know what we are getting into and most of us are more or less okay with it. It's different times and different kinds of users. That explains why Microsoft and Facebook do not get penalized as heavily as Sourceforge did. Sourceforge violated something that was held sacred during those times. Microsoft and Facebook have no notion of sacred-anything.
Websense blacklisted Sourceforge after the 2013 DevShare debacle. It has remained blacklisted since. It is blacklisted in many other web application firewalls and content gateways too. Sourceforge is inaccessible from many corporate networks due to this. It will remain inaccessible for many more years to come.
It's unfortunate how Sourceforge, once a leader in the open source community, lost the trust and reputation it built over 14 years in a matter of a few weeks. It may take another 14 years to regain this lost trust and even that may not be enough.
It's worth pointing out that SourceForge as we knew it back then ceased to exist quite some time ago. SourceForge was sold to DHI Group, Inc. (DICE's parent company) in 2012 and many of the staff were let go as part of the sale. DevShare came into play in 2014 and was originally billed as a way to help open source developers who wanted to sign up earn an income from their open source work. But then it wound up using dark patterns and then it was morphed into something more and started to be added to projects that didn't want it done (in violation of some trademarks and the like). This destroyed the good will that still existed around the brand even though most of the folks who made SourceForge SourceForge were long gone.
SourceForge was then sold again in 2016 to BIZX, LLC who killed the DevShare program and started scanning all downloads for malware and other baddies.
You're obviously very frustrated by how people see the service, but you can't blame them.
The GIMP incident made pretty big news, and for many people, the name "SourceForge" will stay equivalent to a malware-injecting host. Anyone who decided to keep the name should have anticipated that.
I'm not frustrated, but these threads show up on HN almost weekly now, with armchair quarterbacks who really are not current on the state of open source opining ill informed opinions. They even know we are new owners who immediately killed all the bad stuff, and still blame us. I cared about SourceForge, so I bought it and removed DevShare, and still get the blame. People know that we having nothing to do with the old owners, but recreational online outrage is fun, so they continue to blame us for saving it. Cognitive dissonance is en vogue right now. I guess if someone's lonely Sunday night is made better by shitting on the people who did everything in their power to save SourceForge, then go for it. I just think people's time can be used better.
Maybe change your name from source forge to something else.
You can rehabilitate the brand, but that will probably take a lot more money than just changing the name.
Edited to add:
On the front page I also see "Business VOIP" and "Cloud Storage" and "Internet speed test". Maybe you want to remove those links and focus on software development.
>It may take another 14 years to regain this lost trust and even that may not be enough.
That's absolutely absurd given how often the biggest names in 'tech' make headlines with one egregious act or another, on a seemingly weekly basis, and continue to march on. As if the tech community can sit atop some moral high ground, thumbing its nose at SourceForge. But nah, let's just keep crapping on a company no longer under the same ownership and no longer committing these acts and hasn't for some time.
> let's just keep crapping on a company no longer under the same ownership
I have no intention of crapping on SourceForge. I am merely making an observation. I think many would agree that users have lost trust in Sourceforge regardless of the history or current state of ownership.
In fact, I used to appreciate loganabbott's (the new president of Sourceforge) attempt to amend SourceForge until today when I see the same person posting insinuating and insulting comments towards potential users.
I have no intention of crapping on SourceForge because SourceForge is largely irrelevant to me. I host my projects on GitHub these days. If GitHub becomes untenable for any reason, I might move to Gitea. But I am definitely not coming back to Sourceforge after seeing these juvenile comments coming off from the president of Sourceforge in this thread. Don't know about others but he has definitely managed to piss me off as a user.
Regarding why Sourceforge gets the kind of flak other companies don't, I have commented about it here: https://news.ycombinator.com/item?id=17281519 (again this is merely a conversation, not a passing of judgement).
Sorry if my comments rubbed you the wrong way, but it's a bit frustrating when these threads pop up weekly, and people feel like it's open license to attack me and my company. We really are doing our best to make SourceForge a trusted destination, but still get the flack as if we were the previous ownership.
This diatribe just tells me Websense and you are not informed on the current state of the open source community. We bought SourceForge in 2016 specifically because we hated what happened with DevShare and killed it on day one. You can continue hating us simply because of the previous owners, but you can probably find better stuff to do with your time. Nobody uses WebSense anymore anyway except for high schools trying to stop students from watching porn during art history class.
You are insinuating both Websense and me that we are not informed about the current state of Sourceforge. Insinuating your potential users like this is in poor taste considering you are the president of Sourceforge.
I am very much aware and I followed the HN thread [1] when you acquired Sourceforge and when you commented extensively trying to reassure us that you will turn Sourceforge around. Sure you have made efforts but I think it is quite clear that the good measures you took came a little too late.
Frankly, your comments in that acquisition thread [1] were more balanced and matured. The comments you are posting in this thread are coming off as immature.
You also seem to be misinformed about Websense. Websense and other web application firewalls and content gateways are very much in use in many corporate networks including mine. Looks like I am not the only one with this issue.[2]
Congratulations on making a successful release. Kudos to you!
I am going to post a concern regarding the increasing layers of abstraction which is not at all directed at your project but at this domain of managing containers, in general, and the never-ending increase in complexity.
So first we find it difficult to manage so many virtual machines, we got Docker which was a good concept.
Then we found it difficult to manage so many Docker-based services so we got Docker Swarm and Kubernetes.
Now it is difficult to manage Kubernetes, so we have got a new project to manage Kubernetes.
There are many tools (paid and free) that assist with managing multiple kubernetes clusters but we still need to make it easy for human intervention.
When an issue is happening with your kubernetes cluster and you need address it immediately, having the information that you need already at your finger tips is insanely useful.
(3am me is going to appreciate it)
However, the problem of managing multiple kubernetes clusters isn't an easy problem to solve but a good problem to have.
It creates a space open for new ideas on how best we make this part of the industry better and kubernetes itself has looked at this problem and suggested a solution with federated cluster.
I don't have a straight forward answer, but I am excited to be part of the solution.
And very likely that's what really happened. I have been in such interviews and it is sometimes hard to guess whether the interviewer wants the practical answer (calling a library function) from engineering standpoint or the conceptual answer (demonstrating that I can implement the inner workings of the function) from CS standpoint. Often I would just ask a follow up question to clarify exactly at which level of abstraction does the interviewer want my solution to be in?
In situations where I offer a solution that does not match the interviewer's expectation, they clarify the expectations.