Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
zergstain
Dec 15, 2005

astr0man posted:

You can do:
pre:
[code="java"]
to get actual syntax highlighting!

So does it add the <? tags for you when use PHP tags?

Adbot
ADBOT LOVES YOU

necrotic
Aug 2, 2005
I owe my brother big time for this!

zergstain posted:

So does it add the <? tags for you when use PHP tags?

Sure does! I did not add the `<? ?>` parts.

php:
<?
echo var_dump("poop");
<?php
echo var_dump("poop");
?>

zergstain
Dec 15, 2005

necrotic posted:

Sure does! I did not add the `<? ?>` parts.

php:
<?
echo var_dump("poop");
<?php
echo var_dump("poop");
?>

Thanks, I was a bit confused when I saw the <? ?> tags and no '$' prefixing any of the variables.

darthbob88
Oct 13, 2011

YOSPOS

seiken posted:

That's bizarre and I don't know why you'd bother. Now you have to add wrapper methods for each Dictionary method you want to use.

A nested dictionary like Dictionary<K1, Dictionary<K2, V>> is equivalent to Dictionary<K, V> where K is a struct with two elements K1 and K2 though, which is a much more useful way to avoid nested generics if you really dislike them for some reason.
Interesting. I have a toy program just for storing and analyzing rainfall, which stores data in a nested dictionary, like Dictionary<Year, Dictionary<Month, Dictionary<Day, inches of rain>>>. You're suggesting I change that to Dictionary<Struct<Year, Month, Day>, inches of rain>? How would I get the combined data for any particular year or month in that year? The only way I can think of is to iterate over the keys looking for the ones with the right year and/or month, which is inefficient.

Nippashish
Nov 2, 2005

Let me see you dance!

darthbob88 posted:

How would I get the combined data for any particular year or month in that year?

How would you get all the data from July for all the years with your current setup?

shrughes
Oct 11, 2008

(call/cc call/cc)
I was thinking oh, just use Dictionary<Tuple<long, DateTime>, Foo> except that still nests templates...

Yeah, that rule is an anti-pattern.

darthbob88 posted:

Interesting. I have a toy program just for storing and analyzing rainfall, which stores data in a nested dictionary, like Dictionary<Year, Dictionary<Month, Dictionary<Day, inches of rain>>>. You're suggesting I change that to Dictionary<Struct<Year, Month, Day>, inches of rain>? How would I get the combined data for any particular year or month in that year? The only way I can think of is to iterate over the keys looking for the ones with the right year and/or month, which is inefficient.

A SortedDictionary, if it has a way to iterate between a range of keys. I just checked and can't see a way. Oh god speaking of coding horrors: https://stackoverflow.com/questions/5301164/how-to-find-point-between-two-keys-in-sorted-dictionary

seiken
Feb 7, 2005

hah ha ha

darthbob88 posted:

Interesting. I have a toy program just for storing and analyzing rainfall, which stores data in a nested dictionary, like Dictionary<Year, Dictionary<Month, Dictionary<Day, inches of rain>>>. You're suggesting I change that to Dictionary<Struct<Year, Month, Day>, inches of rain>? How would I get the combined data for any particular year or month in that year? The only way I can think of is to iterate over the keys looking for the ones with the right year and/or month, which is inefficient.

Yeah, I guess it's not totally equivalent if you're actually making use of the nesting structure because you want to find all elements based on a partial key. Most of the time you see this it's not the case though and you're only actually looking up single elements for which you know the entire key.

If looking up values based on part of a key is super important though, you might want a slightly different structure anyway: with the nested dictionary approach, looking up based on the innermost part of the key is a bunch more expensive than looking up based on the outermost part of the key.

seiken fucked around with this message at 01:15 on Apr 1, 2014

b0lt
Apr 29, 2005

quote:

llvm[0]: ***** Completed Debug+Asserts Build
llvm[0]: ***** Note: Debug build can be 10 times slower than an
llvm[0]: ***** optimized build. Use make ENABLE_OPTIMIZED=1 to
llvm[0]: ***** make an optimized build. Alternatively you can
llvm[0]: ***** configure with --enable-optimized.

This happens at the end of the build :negative:

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

darthbob88 posted:

Interesting. I have a toy program just for storing and analyzing rainfall, which stores data in a nested dictionary, like Dictionary&lt;Year, Dictionary&lt;Month, Dictionary&lt;Day, inches of rain&gt;&gt;&gt;. You're suggesting I change that to Dictionary&lt;Struct&lt;Year, Month, Day&gt;, inches of rain&gt;? How would I get the combined data for any particular year or month in that year? The only way I can think of is to iterate over the keys looking for the ones with the right year and/or month, which is inefficient.

How big is the data set? Your solution seems insane for small or even moderate data sets...so many tiny nested hash tables.

There have been roughly 40,000 days since 1900. That's small enough to store and filter via LINQ operations on a Dictionary<DateTime, float> without too much concern, unless you're doing a ton of filter operations in a tight loop or something.

seiken
Feb 7, 2005

hah ha ha

quote:

I don't think there is a function on SortedDictionary that lets you find elements around the one you need faster than iterating elements. (+1 to BrokenGlass solution)
:stare: I don't really know C#, is this really true, what the hell

Flownerous
Apr 16, 2012
Style rules and appropriate collection type for purpose are two different issues.

If you're looking to perform a variety of queries on a data-set large enough that searching through all the elements is a performance problem then Dictionary is the wrong collection type.

If a Dictionary<Year, Dictionary<Month, Data>> is the appropriate collection type then it comes down to a trade-off between the boilerplate necessary to do it stylishly and the benefits.

darthbob88
Oct 13, 2011

YOSPOS

Nippashish posted:

How would you get all the data from July for all the years with your current setup?

Iterating over each year to find ones which include days in July requires less time than iterating over all days to find ones in July, although that advantage would probably be lost iterating over each day in each July.

seiken posted:

Yeah, I guess it's not totally equivalent if you're actually making use of the nesting structure because you want to find all elements based on a partial key. Most of the time you see this it's not the case though and you're only actually looking up single elements for which you know the entire key.

If looking up values based on part of a key is super important though, you might want a slightly different structure anyway: with the nested dictionary approach, looking up based on the innermost part of the key is a bunch more expensive than looking up based on the outermost part of the key.
Fair enough. I never need the data for any given day; more often it's analyzing the entirety of one month or year, for which purpose a nested dictionary has worked fine, though next time I play with it I'll fix it to use a SortedDictionary keyed on DateTime and filtered with LINQ, because LINQ is great.

Ithaqua posted:

How big is the data set? Your solution seems insane for small or even moderate data sets...so many tiny nested hash tables.

There have been roughly 40,000 days since 1900. That's small enough to store and filter via LINQ operations on a Dictionary<DateTime, float> without too much concern, unless you're doing a ton of filter operations in a tight loop or something.
We've been recording data since some time in 2010, I believe. And actually there aren't so many tiny hashtables; I just dug that project out and it's actually Dictionary<int, Dictionary<int, float[]>>. The array lets me store the day as the index for the datum. So there are in fact only 6 Dictionaries, containing fewer than 50 entries between them. Yeah, I think I'll make it one big array.

Space Kablooey
May 6, 2009



What's the catch other than the string can parse to a really big number?

Unrelated but, I kinda dislike those things because I can never see the catch and it makes me feel stupid. :(



:lol: but I still want to punch this guy.

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

JawnV6 posted:

No. It's not "pretty much do the same thing." You're advocating forking the production code base, hiding all these changes from your tools, then pretending that testing this not-production code has any meaning. Who's in charge of making sure the fake code base and the production code base are in sync?

:wtc:

You change the interface of the actual code to be pass-from-above, and invoke it from a test harness. Why would you fork anything? Do none of your functions take parameters, and instead get their data from a hairball of global state?

Edit:

code:

sumStrings('1','2') // => '3'

In JS, isn't that just

code:

function sumStrings(a, b)
{
  return String(parseInt(a) + parseInt(b));
}

?

Subjunctive fucked around with this message at 04:26 on Apr 1, 2014

Dessert Rose
May 17, 2004

awoken in control of a lucid deep dream...

HardDisk posted:

I kinda dislike those things because I can never see the catch and it makes me feel stupid. :(

Just wait until the catch is a real customer case and you just broke service for them for days.

vOv
Feb 8, 2014

Subjunctive posted:

code:
sumStrings('1','2') // => '3'
In JS, isn't that just

code:
function sumStrings(a, b)
{
  return String(parseInt(a) + parseInt(b));
}
?

Not if you're dealing with numbers larger than 2^53:

code:
> parseInt('9007199254740992') + parseInt('1')
9007199254740992

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

Subjunctive posted:

:wtc:

You change the interface of the actual code to be pass-from-above, and invoke it from a test harness. Why would you fork anything? Do none of your functions take parameters, and instead get their data from a hairball of global state?

That does nothing to solve the problem, right? All you've done is push the dependency up one level. And God help you if you want to add another dependency to a function, and have to go change everywhere it's called.

With proper DI, here's what it looks like:

code:

@Inject @Now Provider<DateTime> currentTimeProvider;

public void someMethod() {
  DateTime now = currentTimeProvider.get();
}

Easily testable (you just need to supply a different binding), and you don't need to gently caress around modifying call sites any time you need to add another dependency.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
Proper DI sure looks a lot like passing arguments via global variables.

JawnV6
Jul 4, 2004

So hot ...
Good. Cram a bunch of ugly global calls into one file and leave the rest of the code base untouched. Don't fork every function or try to cram every bit of state it might ask for into the function signature.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

Plorkyeran posted:

Proper DI sure looks a lot like passing arguments via global variables.

Hardly. Dependency injection replaces constructor calls and static references -things which are already globally scoped even in a program written without DI - and allows you to easily substitute them for testing purposes. It doesn't replace passing parameters - for example, if this function was supposed to format a DateTime such that it was relative to the current time (e.g. "5 seconds ago"), you'd still pass the DateTime to format as a regular parameter.

You can also do inversion of control manually by explicitly passing all the dependencies into the constructor or method call, but that results in a very fragile structure that requires changes all over the place if you want to change the dependency structure in any way, making it really hard to maintain.

return0
Apr 11, 2007
I don't get why people hate the constructor. It's like, jeez just pass the stuff the class needs to the constructor already.

Brecht
Nov 7, 2009

Jabor posted:

And God help you if you want to add another dependency to a function, and have to go change everywhere it's called.
Maybe I've spent too long in static typing land, but if you can add dependencies to a function _without_ changing its signature you're gonna end up in a really bad place really quickly.

Or, put another way: the horror is you

Brecht
Nov 7, 2009

Jabor posted:

You can also do inversion of control manually by explicitly passing all the dependencies into the constructor or method call, but that results in a very fragile structure that requires changes all over the place if you want to change the dependency structure in any way, making it really hard to maintain.
Yeah, this is the opposite of what is true. The horror is coming from inside the thread.

Cancelbot
Nov 22, 2006

Canceling spam since 1928

seiken posted:

That's bizarre and I don't know why you'd bother. Now you have to add wrapper methods for each Dictionary method you want to use.

A nested dictionary like Dictionary<K1, Dictionary<K2, V>> is equivalent to Dictionary<K, V> where K is a struct with two elements K1 and K2 though, which is a much more useful way to avoid nested generics if you really dislike them for some reason.

For the example I posted your way would certainly be better, the current implementation is overkill as both dictionaries are tiny and the long/datetime are strongly linked.

I try to not be strict; but the job I had before this treated FxCop as the be-all-end-all of programming style which would break the build on warning levels of reporting. Three years of that and my fingers get itchy when I see more than one angle bracket next to each other and it's not a shift.

Then again there's this question related to a class overloading ">>" in a contrived way;
http://stackoverflow.com/questions/10610459/nested-generic-syntax-ambiguity

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
Just an example to put this stuff in context, since most enterprise software design patterns tend to be unnecessary and look clumsy for toy programs:

Suppose we're building a document-management application. One of the things your document management application does is share documents between users. You've written a component to handle that sharing process.

Now you want to have a widget that shares a particular document. You could have the widget instantiate an instance of your sharing component, but that's pretty untestable. You could pass in an instance when you're creating the widget, but now everything that uses the widget needs to know that it depends on your sharing component, and if you change your mind later you need to also change everything that uses your widget - it's fragile and it's not very good at encapsulating how the widget works. Using a DI framework solves the testability issue without forcing every component in your program to care about the internal workings and dependencies of every other component they make use of.

Athas
Aug 6, 2007

fuck that joker

JawnV6 posted:

Good. Cram a bunch of ugly global calls into one file and leave the rest of the code base untouched. Don't fork every function or try to cram every bit of state it might ask for into the function signature.

Hello, I write Haskell at my job, and this is pretty much necessary. As for a horror...

code:
runFunNoTrace :: Name -> [Value] -> Prog -> Either InterpreterError [Value]
runFunNoTrace = ((.) . (.) . (.)) fst runFun

Zombywuf
Mar 29, 2008

Athas posted:

code:
runFunNoTrace :: Name -> [Value] -> Prog -> Either InterpreterError [Value]
runFunNoTrace = ((.) . (.) . (.)) fst runFun

Is it wrong that this makes me think of Total Recall?

Athas
Aug 6, 2007

fuck that joker

Zombywuf posted:

Is it wrong that this makes me think of Total Recall?

Not at all! I was in fact thinking about what to call this pattern, given that its smaller cousin '(.) . (.)' has a pretty obvious name.

Sagacity
May 2, 2003
Hopefully my epitaph will be funnier than my custom title.

JawnV6 posted:

Good. Cram a bunch of ugly global calls into one file and leave the rest of the code base untouched. Don't fork every function or try to cram every bit of state it might ask for into the function signature.
Is the "Fine whatEVS!" approach how you handle every discussion?

gonadic io
Feb 16, 2011

>>=

Athas posted:

Hello, I write Haskell at my job, and this is pretty much necessary. As for a horror...

code:
runFunNoTrace :: Name -> [Value] -> Prog -> Either InterpreterError [Value]
runFunNoTrace = ((.) . (.) . (.)) fst runFun

Somebody learnt to program in Forth clearly :v:

e: alternatively, this is slightly shorter way clearer!
code:
runFunNoTrace = ((fst .) .) . runFun

gonadic io fucked around with this message at 12:06 on Apr 1, 2014

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer
Let me see if I understand this. (.) . (.) takes a function that's missing exactly two parameters and composes it with another function that expects the return type of the first function as its first input parameter. Is that right?
code:
let boobs = (.) . (.)
let subtract x y = x-y
let double x = x*2
let subtractAndDouble = double `boobs` subtract
I need to use the boobs operator because double . subtract doesn't type check. It works if there's only one missing parameter to the second function:
code:
let subtractFromFive x = 5-x
let double x = x*2
let subtractFromFiveAndDouble = double . subtractFromFive
And triple boobs lets me do the same thing when there are exactly three missing parameters?
code:
let totalRecall = (.) . (.) . (.)
let multiSubtract x y z = x-y-z
let double x = x*2
let multiSubtractAndDouble = double `totalRecall` multiSubtract
I like pointfree style and all, but this is pretty ridiculous. Can Haskell programmers actually read this stuff? And why is there no Haskell thread?

AlsoD posted:

Somebody learnt to program in Forth clearly :v:

e: alternatively, this is slightly shorter way clearer!
code:
runFunNoTrace = ((fst .) .) . runFun

That is... not clearer to me.

gonadic io
Feb 16, 2011

>>=

LOOK I AM A TURTLE posted:

Let me see if I understand this. (.) . (.) takes a function that's missing exactly two parameters and composes it with another function that expects the return type of the first function as its first input parameter. Is that right?

I like pointfree style and all, but this is pretty ridiculous. Can Haskell programmers actually read this stuff? And why is there no Haskell thread?

That is... not clearer to me.

Yes you're correct, yes it's pretty ridiculous (hence why it's a horror). The correct way to write that function would be
code:
runFunNoTrace :: Name -> [Value] -> Prog -> Either InterpreterError [Value]
runFunNoTrace name values prog = fst $ runFun name values prog
Point-free programming is often called point-less programming for this very reason as sometimes it just makes things a little less cluttered but taken too far you end up programming in what is effectively a stack-based language (hence my Forth joke) and it is just obfuscation for the sake of feeling clever.

There was a Haskell thread in CoC for a little while but it didn't see much traffic. Functional programming comes up in the YOSPOS programming thread a fair amount though if you want to discuss it there.

There's also been some suggestion to recognise the boobs operators with
code:
(.:)  = (.) . (.)
(.::) = (.) . (.:)
but not many people are in favour since its only task is to make code harder to read for a tiny conciseness benefit.

e: Although this hasn't stopped me from defining these functions when I need then in my toy code and I wouldn't hesitate to use runFunNoTrace = fst .:: runFun in a personal project.

gonadic io fucked around with this message at 13:21 on Apr 1, 2014

gonadic io
Feb 16, 2011

>>=
As for my horror:
code:
totalValue, totalWeight :: Solution -> Int

instance Ord Solution where
    compare = comparing totalValue <> comparing (Down . totalWeight)
Who can tell me what Monoid instance that is?
Monoid (Solution -> Solution -> Ordering)

JawnV6
Jul 4, 2004

So hot ...

Athas posted:

Hello, I write Haskell at my job, and this is pretty much necessary. As for a horror...
Right, comparing a functional language's manipulation of state is totally germane to a conversation about DI in managed languages.

Sagacity posted:

Is the "Fine whatEVS!" approach how you handle every discussion?
I'm talking about a single higher-level principle about how to test code. Testing should be done on "actual code." I didn't think this would be nearly so contentious a proposition, but here we are. For my embedded work ripping away all the micro-specific stuff and stuffing it into a HAL is most of that effort, so that the relevant code is testable in it's abstract state without building a simulator for every flavor of micro that we see. For C# it's using DI to change where a function calls point to test the functionality in a mock environment. I want to check that my code can handle the DateTime cases around leap years and instead of moving some blocks around behind the scenes and leaving production code untouched you're still advocating mucking up the function parameters to pass that information in as if it's tenable for all cases. You've tried to hide it behind gussied up language lauding the superhuman code crafters we mortals couldn't bear to view and how they'd obviously avoid every specific case without having functions having to pull every instance of state they might try to sample or forking the code base and testing that.

You're advocating changing parameters as a way to avoid DI. I tried mentioning a case where a dependency is used twice, forcing this method to add another parameter to the function and highlight how ridiculous it is to try to avoid dependencies by smuggling all this information around in the function signature, you :spergin: out on the details. I tried to retreat to the clear principle of "run tests against Actual Production Code" and you again defend your lovely parameter idea. Changing parameters either uglies up all the code everywhere or you're forking it and testing fake code against a fake environment. All of the "ugly boilerplate" you're ranting against as if it's the root of all evil is in one file apart from the production code base.

So yeah, after 3~4 passes against your lovely disingenuous arguments that refuse to step back and see the forest for the trees, I guess I'm a little short and pithy. I could take another swing, but I'm pretty sure you'll just retreat to complimenting all the amazing humans you work with and avoiding the relevant bits of the discussion.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

Jabor posted:

Hardly. Dependency injection replaces constructor calls and static references -things which are already globally scoped even in a program written without DI - and allows you to easily substitute them for testing purposes.
i.e. DI consists of replacing immutable global state with mutable global state to spare you from realizing that your functions take too many arguments.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

JawnV6 posted:

You're advocating changing parameters as a way to avoid DI. I tried mentioning a case where a dependency is used twice, forcing this method to add another parameter to the function and highlight how ridiculous it is to try to avoid dependencies by smuggling all this information around in the function signature, you :spergin: out on the details. I tried to retreat to the clear principle of "run tests against Actual Production Code" and you again defend your lovely parameter idea. Changing parameters either uglies up all the code everywhere or you're forking it and testing fake code against a fake environment. All of the "ugly boilerplate" you're ranting against as if it's the root of all evil is in one file apart from the production code base.

You're literally advocating using global variables to avoid having to pass arguments to a function.

JawnV6
Jul 4, 2004

So hot ...

Plorkyeran posted:

You're literally advocating using global variables to avoid having to pass arguments to a function.

And if this EGREGIOUS SIN lets us test production code without modification? Can you put those two values up against each other and make a conscious decision or is one so utterly abhorrent that you can't give it any space? I'd welcome a nuanced argument. Saying "gloooobal" with the boogeyman voice doesn't cut it.

I do embedded work. Globals are called "RAM."

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
Well yes, we can have a discussion about when using global variables is and isn't worth it if you're done trying to claim that you aren't using global variables at all.

Germstore
Oct 17, 2012

A Serious Candidate For a Serious Time
I don't see the problem with global state as long as it is effectively immutable.

Adbot
ADBOT LOVES YOU

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
For example, in Python I'm moderately a fan of the following general pattern for mocking out deps for tests:

Python code:
class Foo:
    def _get_now_provider(self):
        return lambda: datetime.now()

    def do_stuff(self):
        now = self._get_now_provider()()
        ...

@patch.object(Foo, '_get_now_provider')
def test(_get_now_provider):
    _get_now_provider.return_value = lambda: datetime.date(2001, 1, 1)
    Foo().do_stuff()
Here, the global state being modified for testing is the class object itself. This is "icky", but doesn't have the following problems I've encountered with real code using IoC containers for DI:

The default implementation is right next to the thing using it, rather than being off in some other class whose name may not even appear in the file. This helps reduce DI's tendency to turn code into ravioli.

mock.patch is very clearly a unit testing thing. Using it to switch implementations based on a value in a config file would be obviously completely insane. OTOH, it seems to be an inevitable result of using IoC containers, since they do handle that quite well. However, this leads to your non-test code relying on mutable global state as a non-implementation-detail, which generally turns into a mess. "Don't monkey-patch classes outside of test code" seems to be a much simpler rule for people to follow than "Don't use this library that we're using for other things to solve a problem it appears to solve well but actually doesn't".

It doesn't lead as much to "gently caress it, let's DI all the things, including the things that we don't actually have to mock out for tests". IoC containers are a workaround for the fact that the language makes it excessively awkward to explicitly pass in all of an object's dependencies. However, sometimes (often) an object's dependency really is a logical part of its interface and should be explicitly passed in, even though it can be magically instantiated by the DI stuff. Automatic DI should be used only for things that are implementation details of the class, but because it's "easier" it tends to get used for more than that.

It of course also has far less boilerplate, but that's mostly a result of Python vs. Java (although some people do seem to really like writing Java amounts of boilerplate in Python).

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply