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
taqueso
Mar 8, 2004


:911:
:wookie: :thermidor: :wookie:
:dehumanize:

:pirate::hf::tinfoil:

chippy posted:

I just found this line of C# to check that two ints (noDetails, noPictures) are equal. it took me a second to even parse it's purpose.

code:
var areEqual = new[] { noDetails, noPictures }.Distinct().Count() == 1;

I know I'm a little late and this is C#. I'm not a rust genius, but wouldn't the equivalent in rust compile to a simple comparison? (I've been reading the rust book so it is on my mind)

Seems like it is one step away from being generic for any size collection.

e: pre-emptive "this isn't clearer and isn't better code than the standard aaa == bbb for this case, just musing"

taqueso fucked around with this message at 15:31 on Mar 8, 2018

Adbot
ADBOT LOVES YOU

putin is a cunt
Apr 5, 2007

BOY DO I SURE ENJOY TRASH. THERE'S NOTHING MORE I LOVE THAN TO SIT DOWN IN FRONT OF THE BIG SCREEN AND EAT A BIIIIG STEAMY BOWL OF SHIT. WARNER BROS CAN COME OVER TO MY HOUSE AND ASSFUCK MY MOM WHILE I WATCH AND I WOULD CERTIFY IT FRESH, NO QUESTION

Bruegels Fuckbooks posted:

isn't that present tense? i mean, facebook did move from "Move fast and break things" to "Move Fast With Stable Infra," and google has progressed to actually supporting products for longer than a year before the programmers get bored, but job postings are still slobbering all over the agile bullshit, and the visionaries at my company decided to take the SAFe agile poo poo seriously so within the past two weeks, my inbox has been clogged with diagrams that look like:


It is definitely present tense. And I don't think agile is to blame so much as misapplication of it.

Steve French
Sep 8, 2003

a hot gujju bhabhi posted:

It is definitely present tense. And I don't think agile is to blame so much as misapplication of it.

You know what to call a tool that nobody can figure out how to use correctly?

A lovely tool.

CPColin
Sep 9, 2003

Big ol' smile.
You know what you call a person who buys a pre-filled toolbox, dumps everything out onto the ground, puts a blindfold on, and starts swinging the tools around randomly?

A manager.

HappyHippo
Nov 19, 2003
Do you have an Air Miles Card?

Steve French posted:

You know what to call a tool that nobody can figure out how to use correctly?

A lovely tool.

While I generally agree with this sentiment, in this case I think what happened is a bunch of marketers and consultants turned agile into Agile™ in order to cash in on the hype. Of course that means it has to be as complicated as possible because otherwise you wouldn't need to pay consultants to tell you how to figure it out

canis minor
May 4, 2011

Bruegels Fuckbooks posted:

isn't that present tense? i mean, facebook did move from "Move fast and break things" to "Move Fast With Stable Infra," and google has progressed to actually supporting products for longer than a year before the programmers get bored, but job postings are still slobbering all over the agile bullshit, and the visionaries at my company decided to take the SAFe agile poo poo seriously so within the past two weeks, my inbox has been clogged with diagrams that look like:


I'm an enabler

:eng99:

NihilCredo
Jun 6, 2011

iram omni possibili modo preme:
plus una illa te diffamabit, quam multæ virtutes commendabunt

taqueso posted:

I know I'm a little late and this is C#. I'm not a rust genius, but wouldn't the equivalent in rust compile to a simple comparison? (I've been reading the rust book so it is on my mind)

Seems like it is one step away from being generic for any size collection.

e: pre-emptive "this isn't clearer and isn't better code than the standard aaa == bbb for this case, just musing"

My attempt (I don't actually know Rust):

https://godbolt.org/g/uXWQLx

The generated assembly definitely isn't a simple comparison, but maybe you're thinking of a different implementation that does get optimized?


C# definitely doesn't optimize it, of course:

https://dotnetfiddle.net/QHsGcv

code:
    IL_0001:  ldc.i4.0
    IL_0002:  stloc.0
    IL_0003:  ldc.i4.1
    IL_0004:  stloc.1
    IL_0005:  ldc.i4.2
    IL_0006:  newarr     [mscorlib]System.Int32
    IL_000b:  stloc.3
    IL_000c:  ldloc.3
    IL_000d:  ldc.i4.0
    IL_000e:  ldloc.0
    IL_000f:  stelem.i4
    IL_0010:  ldloc.3
    IL_0011:  ldc.i4.1
    IL_0012:  ldloc.1
    IL_0013:  stelem.i4
    IL_0014:  ldloc.3
    IL_0015:  call       class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0> [System.Core]System.Linq.Enumerable::Distinct<int32>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>)
    IL_001a:  call       int32 [System.Core]System.Linq.Enumerable::Count<int32>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>)
    IL_001f:  ldc.i4.1
    IL_0020:  ceq
    IL_0022:  stloc.2
    IL_0023:  ret

chippy
Aug 16, 2006

OK I DON'T GET IT

taqueso posted:

I know I'm a little late and this is C#. I'm not a rust genius, but wouldn't the equivalent in rust compile to a simple comparison? (I've been reading the rust book so it is on my mind)

Seems like it is one step away from being generic for any size collection.

e: pre-emptive "this isn't clearer and isn't better code than the standard aaa == bbb for this case, just musing"

I don't know Rust, or enough about any compiler to know if any of them would optimise this away to a single comparison.

And yeah, you're right, it's not a bad way to do it for a variable-sized collection really. It also looks quite a lot like something I would write if I was dealing with a variable number of ints*, and not something something the dev in question would write; he would almost definitely use a loop. So I can only conclude he actually lifted the pattern from some of my code, but why he went to the trouble of doing that instead of just writing isEqual = noDetails == noPictures is beyond me.

*e: Actually, I'd probably be more likely to do something like
code:
allEqual = listOfInts.All(x => x == listOfInts.First())
, after checking the list is not empty obviously. It would probably perform a fair bit better because All() will exit and return false as soon as it finds an unequal value, instead of having to Distinct() and Count() an entire list just to find that out.

chippy fucked around with this message at 17:17 on Mar 8, 2018

Steve French
Sep 8, 2003

HappyHippo posted:

While I generally agree with this sentiment, in this case I think what happened is a bunch of marketers and consultants turned agile into Agile™ in order to cash in on the hype. Of course that means it has to be as complicated as possible because otherwise you wouldn't need to pay consultants to tell you how to figure it out

Oh yes, this most definitely happened as well. And not just complicated, but also rigidly defined (again, why else would you be paying someone to tell you how to do poo poo?), also as far as I can tell running entirely counter to the ostensible core principles of agile.

Klades
Sep 8, 2011

I work on an embedded system. It has a lot of... "fun" issues that I could talk about, but for now here's a thing I hit yesterday.

The system is in three parts:
There's the main part, which is basically the manager and is mostly facilitating communication between the other parts, the outside world, and the OS.
Then there's the part doing most of the heavy lifting, which is off on its own CPU.
Then there's the GUI, which is on the same CPU as the manager.

These all use TCP to communicate :stonk:

One of the things the (horrible and terrible and poo poo) GUI lets you do is set the time. Yesterday it was noted that doing so would, depending on your machine, either not work or crash the GUI.
This was pretty strange, so I looked into it.

1) The GUI figured out what year you'd indicated (from the scrolling list of years) by doing a string->int parse on the current selection. But the list of years only goes back to 2017, so if your device was set to an earlier date for some reason (like the default, 1970), it would fail to put the dial on a valid date to start with, which would for some reason also prevent it from changing when you scrolled it, and an attempt to get the current selection would return null and this is QML, which means javascript, which means quiet failure at runtime. This is why on some machines setting the date in the GUI simply wouldn't work.

2) In all cases where one component needs to send a message and get a response, there's a timeout period of 5 seconds after which it is assumed that the other component has had an issue and the communication is aborted. I realized that sometimes this timeout was happening instantly when changing the date. I wonder what the code handling this looks like...
code:
// Paraphrasing
double start = current_time();
double timeout = 5000;
send_message(); // This is the bit that would tell the manager app the new date and time
while (true) {
  wait_for_reply(); // this blocks until something wakes it back up
  double elapsed = current_time() - start;
  if (elapsed > timeout) {
    // bail out
  }
  if (message_ok())
    break;
}
:eng99:

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



Jabor posted:

Also the name is literally a racial slur.

I thought it was ableist :confused:

Also since nobody mentioned the thing where their code was written to randomly discard 90% of log messages about a particular error because it happened too often I'm gonna bring it up because lmao

https://stackoverflow.com/questions/16833100/why-does-the-mongodb-java-driver-use-a-random-number-generator-in-a-conditional

iospace
Jan 19, 2038


So with Agile falling out of vogue, is it time to go back to Waterfall?

Doom Mathematic
Sep 2, 2008
Agile and Waterfall are not mutually exclusive. They aren't even the same kind of thing.

NihilCredo
Jun 6, 2011

iram omni possibili modo preme:
plus una illa te diffamabit, quam multæ virtutes commendabunt

chippy posted:

*e: Actually, I'd probably be more likely to do something like
code:
allEqual = listOfInts.All(x => x == listOfInts.First())
, after checking the list is not empty obviously.

No need to do that, if the list is empty .All() will immediately return true anyway :eng101:

taqueso
Mar 8, 2004


:911:
:wookie: :thermidor: :wookie:
:dehumanize:

:pirate::hf::tinfoil:

chippy posted:

I don't know Rust, or enough about any compiler to know if any of them would optimise this away to a single comparison.

And yeah, you're right, it's not a bad way to do it for a variable-sized collection really. It also looks quite a lot like something I would write if I was dealing with a variable number of ints*, and not something something the dev in question would write; he would almost definitely use a loop. So I can only conclude he actually lifted the pattern from some of my code, but why he went to the trouble of doing that instead of just writing isEqual = noDetails == noPictures is beyond me.

*e: Actually, I'd probably be more likely to do something like
code:
allEqual = listOfInts.All(x => x == listOfInts.First())
, after checking the list is not empty obviously. It would probably perform a fair bit better because All() will exit and return false as soon as it finds an unequal value, instead of having to Distinct() and Count() an entire list just to find that out.

I'm at work right now, but I am super out of rust practice so this will be a fun exercise to try in a few hours. I'll see what I get with a few methods. I think the data will have to be in the form of a tuple or something else that has a fixed size instead of a vec to get the magic to happen. You get different machine code for each type, so it should generate an implementation for vectors of u32, vectors of u64, each size of tuple etc. (afaik ...)

taqueso fucked around with this message at 18:46 on Mar 8, 2018

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:

NihilCredo posted:

No need to do that, if the list is empty .All() will immediately return true anyway :eng101:

If you're attempting to mimic the behavior of Distinct().Count() == 1, then you'd want it to return false on an empty list.

That aside, the First call should probably be brought out of the predicate, and if you want the code to be suited for any IEnumerable<int>, then it'd have to be written completely differently.

Jeb Bush 2012
Apr 4, 2007

A mathematician, like a painter or poet, is a maker of patterns. If his patterns are more permanent than theirs, it is because they are made with ideas.

QuarkJets posted:

You only dislike the weak bosons because they have a mean decay time greater than your longest-held erection

Send your wife over my way I will show her what real alpha decay looks like

this is the most owned I have been since 50 CERN researchers published a paper on my "low energy physics"

QuarkJets
Sep 8, 2008

Jeb Bush 2012 posted:

this is the most owned I have been since 50 CERN researchers published a paper on my "low energy physics"

Oh hey I remember you, our arxiv post suggested that your manhood represented a breakthrough discovery because even in an excited state it has less energy than the vacuum ground state lol. Tell your mom that the ATLAS liquid argon calorimetry group says hi

(BTW argon is odorless, unlike your breath)

canis minor
May 4, 2011


This is all wonderful, terrifying and soul-crushing.

putin is a cunt
Apr 5, 2007

BOY DO I SURE ENJOY TRASH. THERE'S NOTHING MORE I LOVE THAN TO SIT DOWN IN FRONT OF THE BIG SCREEN AND EAT A BIIIIG STEAMY BOWL OF SHIT. WARNER BROS CAN COME OVER TO MY HOUSE AND ASSFUCK MY MOM WHILE I WATCH AND I WOULD CERTIFY IT FRESH, NO QUESTION

Steve French posted:

You know what to call a tool that nobody can figure out how to use correctly?

A lovely tool.

I didn't say nobody could figure it out, I said that some people were using it poorly or incorrectly.

Anyway, I finally have a coding horror to share. The place I work at unfortunately had a team of very incompetent developers who would do all kinds of crazy poo poo, and I've been meaning to find a tidy snippet without too much business specific stuff in it so I could post it here:

code:
.ForMember(x => x.Fart, opt => opt.MapFrom(src => 
    src.Butt == 2
        ? Constants.SomeInt
        : src.Butt == 3
            ? Constants.SomeOtherInt
            : src.Butt == 5 || (src.Butt == 1 && src.Penis != null)
                ? Constants.YetAnotherInt
                : src.Butt == 1
                    ? Constants.LastInt
                    : Constants.ActualLastInt))
The worst thing? This is from one of the current team members. Magic numbers, chained ternaries, it's a thing of beauty.

VikingofRock
Aug 24, 2008




taqueso posted:

I know I'm a little late and this is C#. I'm not a rust genius, but wouldn't the equivalent in rust compile to a simple comparison? (I've been reading the rust book so it is on my mind)

Seems like it is one step away from being generic for any size collection.

e: pre-emptive "this isn't clearer and isn't better code than the standard aaa == bbb for this case, just musing"

Just tested it out, and the answer is yes! Both for iterator-style and imperative style.

Input:

Rust code:
extern crate itertools;

#[no_mangle]
pub fn foo_iter(x: u32, y: u32) -> bool {
    use itertools::Itertools;
    vec![x, y].into_iter().dedup().count() == 1
}

#[no_mangle]
pub fn foo_imperative(x: u32, y: u32) -> bool {
    let mut v = vec![x, y];
    v.dedup();
    v.len() == 1
}
output assembly (compiled with --release, lto=true):

code:
	.section	__TEXT,__text,regular,pure_instructions
	.globl	_foo_iter
	.p2align	4, 0x90
_foo_iter:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset %rbp, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register %rbp
	cmpl	%esi, %edi
	sete	%al
	popq	%rbp
	retq
	.cfi_endproc

	.globl	_foo_imperative
	.p2align	4, 0x90
_foo_imperative:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset %rbp, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register %rbp
	cmpl	%edi, %esi
	sete	%al
	popq	%rbp
	retq
	.cfi_endproc


.subsections_via_symbols
I'm impressed.

Eela6
May 25, 2007
Shredded Hen

VikingofRock posted:

Just tested it out, and the answer is yes! Both for iterator-style and imperative style.

Input:

Rust code:
extern crate itertools;

#[no_mangle]
pub fn foo_iter(x: u32, y: u32) -> bool {
    use itertools::Itertools;
    vec![x, y].into_iter().dedup().count() == 1
}

#[no_mangle]
pub fn foo_imperative(x: u32, y: u32) -> bool {
    let mut v = vec![x, y];
    v.dedup();
    v.len() == 1
}
output assembly (compiled with --release, lto=true):

code:
	.section	__TEXT,__text,regular,pure_instructions
	.globl	_foo_iter
	.p2align	4, 0x90
_foo_iter:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset %rbp, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register %rbp
	cmpl	%esi, %edi
	sete	%al
	popq	%rbp
	retq
	.cfi_endproc

	.globl	_foo_imperative
	.p2align	4, 0x90
_foo_imperative:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset %rbp, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register %rbp
	cmpl	%edi, %esi
	sete	%al
	popq	%rbp
	retq
	.cfi_endproc


.subsections_via_symbols
I'm impressed.

That's wild. I would be interested to hear about the compiler magic behind that.

putrid aidsman
Apr 13, 2017

by Lowtax

Doom Mathematic posted:

Agile and Waterfall are not mutually exclusive. They aren't even the same kind of thing.

explain

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

QuarkJets posted:

Oh hey I remember you, our arxiv post suggested that your manhood represented a breakthrough discovery because even in an excited state it has less energy than the vacuum ground state lol. Tell your mom that the ATLAS liquid argon calorimetry group says hi

(BTW argon is odorless, unlike your breath)

I was working late in the department one night when who should step out from behind the vending machine but QuarkJets. "I heard they detected gravitational waves," he began as I mentally steeled myself. "Shoulda just pointed they detectors at you getting out of bed in the morning." I gritted my teeth as he continued, "Only thing that moves faster than the speed of light is the female grad students leaving any party you show your face at".

I hurried back to my office and sat at my machine to work on my simulation, but QuarkJets's face appeared on the monitor. He continued, "And yo particle accelerator look like a dishwasher" and I was like drat

taqueso
Mar 8, 2004


:911:
:wookie: :thermidor: :wookie:
:dehumanize:

:pirate::hf::tinfoil:

Rust code:
extern crate itertools;

use std::iter::IntoIterator;
use itertools::Itertools;

pub fn foo_generic<T, U>(items: T) -> bool
where T: IntoIterator<Item=U>,
      U: PartialEq
{
    items.into_iter().dedup().count() == 1
}
This works with slices and vectors, but I'm getting lost looking at the source output trying to find the code generated. I have to go for a bit but I wanted to post it before I left.

Linear Zoetrope
Nov 28, 2011

A hero must cook

Eela6 posted:

That's wild. I would be interested to hear about the compiler magic behind that.

IIRC, it's called loop or stream fusion and largely something LLVM does to the IR Rust generates. Rust's immutability guarantees help a lot (GHC does something similar). I think it's still really, really easy to accidentally break it if you use iterators in slightly the wrong way, though (like putting external closures in filter or fold functions for instance).

E:

The idea behind fusion is if you have something like

code:
for i in 0..n {
    out[i] = foo(list[i])
}

for j in 0..m {
    out2[j] = bar(out[j])
}
The compiler can, in many cases, prove this is silly because out is never used past the second loop and reduce it to

code:
for i in 0..min(m,n) {
    out[i] = foo(bar(list[i]))
}
And then, of course, from there it can perform further optimizations to foo(bar(list[i])) such as inlining, composing function calls, or whatever else. (Or to the assignment, assigning back to, e.g., the same memory as list if that variable is never used after that). Stream fusion is the same concept applied to iterators. From there, if everything is immutable you can do even further optimizations to the results. It's still really easy to break if you throw in the slightest monkey wrench that it may not be able to prove (say relying on the result of a closure that references arbitrary memory), but it can go a long way.

taqueso posted:

Rust code:
extern crate itertools;

use std::iter::IntoIterator;
use itertools::Itertools;

pub fn foo_generic<T, U>(items: T) -> bool
where T: IntoIterator<Item=U>,
      U: PartialEq
{
    items.into_iter().dedup().count() == 1
}
This works with slices and vectors, but I'm getting lost looking at the source output trying to find the code generated. I have to go for a bit but I wanted to post it before I left.

Keep in mind that it may be optimizing the function out entirely if it or LLVM decide that everything evaluates to true/false because you're using obvious constants. It's why the black_box function exists for benchmarks, to prevent the compiler from throwing away function calls that obviously evaluate to something at compile time.

Linear Zoetrope fucked around with this message at 03:06 on Mar 9, 2018

Spatial
Nov 15, 2007

C++ code:
    // Have to do this twice or it doesn't detect devices on startup. lol
    for (uint32_t i=0; i<2; i++) {
        USB_Init( HIDIF.Config.PortNumber, USB_MODE_Host );
    }
Is the horror me or the USB library? If you don't initialise it twice it doesn't detect devices unless you plug them out then back in.

Now the true horror. Why did I even think to do this? Embedded development!

:unsmigghh:

Spatial fucked around with this message at 03:19 on Mar 9, 2018

JawnV6
Jul 4, 2004

So hot ...

Spatial posted:

C++ code:
    // Have to do this twice or it doesn't detect devices on startup. lol
    for (uint32_t i=0; i<2; i++) {
        USB_Init( HIDIF.Config.PortNumber, USB_MODE_Host );
    }
Is the horror me or the USB library?

The USB library, the you-horror version is
C++ code:
    // wtffffff
while(1);
  USB_Init( HIDIF.Config.PortNumber, USB_MODE_Host );
    USB_Init( HIDIF.Config.PortNumber, USB_MODE_Host );
//USB_Init( HIDIF.Config.PortNumber, USB_MODE_Device );// ???
//USB_INIT(0, 0);;
   USB_Init( HIDIF.Config.PortNumber, USB_MODE_Host );

Steve French
Sep 8, 2003

a hot gujju bhabhi posted:

I didn't say nobody could figure it out, I said that some people were using it poorly or incorrectly.

Yeah, I know you weren't saying that, and I didn't mean to imply that you were, though now I see that I did.

What I was alluding to is that agile horror stories are incredibly common, and almost always someone responds to them with a suggestion or claim that they weren't doing it right.

Well, yeah.

The indication to me here when that's so common is that it's a failure of the tool, not just a failure of those misusing it.

There have been lots of discussions about Git here, and the sharp edges it has, and inevitably someone responds with a comment about how it's really not that hard and something about directed graphs. Personally, I don't have issues with it, but I totally get the perspective that when those issues are so common, there's a tool problem, even though I have seen it used very well.

I think of agile in the same way

putin is a cunt
Apr 5, 2007

BOY DO I SURE ENJOY TRASH. THERE'S NOTHING MORE I LOVE THAN TO SIT DOWN IN FRONT OF THE BIG SCREEN AND EAT A BIIIIG STEAMY BOWL OF SHIT. WARNER BROS CAN COME OVER TO MY HOUSE AND ASSFUCK MY MOM WHILE I WATCH AND I WOULD CERTIFY IT FRESH, NO QUESTION

Steve French posted:

Yeah, I know you weren't saying that, and I didn't mean to imply that you were, though now I see that I did.

What I was alluding to is that agile horror stories are incredibly common, and almost always someone responds to them with a suggestion or claim that they weren't doing it right.

Well, yeah.

The indication to me here when that's so common is that it's a failure of the tool, not just a failure of those misusing it.

There have been lots of discussions about Git here, and the sharp edges it has, and inevitably someone responds with a comment about how it's really not that hard and something about directed graphs. Personally, I don't have issues with it, but I totally get the perspective that when those issues are so common, there's a tool problem, even though I have seen it used very well.

I think of agile in the same way

Fair enough, although thinking of agile as a tool is part of the problem I think. It's really more of a guideline for good practices, or at least it should be used that way. When it's used as a mantra that's when poo poo starts to fall apart. So yeah, it is flawed in that if you try to follow it 100% to the letter, you'll get burned, but I don't think that's how it was ever supposed to be used. I've always seen it as "here's a bunch of ways that you can improve your software development lifecycle, take or leave whichever ones are appropriate for your business". That being said, I admit this is just my reading of it and maybe it is meant to be more stringently applied, in which case, yeah it's not a good thing.

VikingofRock
Aug 24, 2008




taqueso posted:

Rust code:
extern crate itertools;

use std::iter::IntoIterator;
use itertools::Itertools;

pub fn foo_generic<T, U>(items: T) -> bool
where T: IntoIterator<Item=U>,
      U: PartialEq
{
    items.into_iter().dedup().count() == 1
}
This works with slices and vectors, but I'm getting lost looking at the source output trying to find the code generated. I have to go for a bit but I wanted to post it before I left.

If you want to re-implement / play around with what I did, here's my Cargo.toml:

code:
[package]
name = "test-lib"
version = "0.1.0"
authors = ["VikingofRock"]

[dependencies]
itertools = "0.7"

[profile.release]
lto = true
I compile with RUSTFLAGS="--emit asm" cargo build --release, and then the assembly is in target/release/deps/my-lib-1a2b3c4d5e6.s

repiv
Aug 13, 2009

Rust Playground allows you to import the most popular crates (which includes itertools) so you can easily peek at the disassembly on there

https://play.rust-lang.org/?gist=95ac417519ad84d133ac7982bc496059&version=stable

iospace
Jan 19, 2038


Doom Mathematic posted:

Agile and Waterfall are not mutually exclusive. They aren't even the same kind of thing.

Please explain how they're A. not mutually exclusive, and B. not even the same kind of thing.

Volguus
Mar 3, 2009

iospace posted:

Please explain how they're A. not mutually exclusive, and B. not even the same kind of thing.

You can apply waterfall within a sprint don't you?

TooMuchAbstraction
Oct 14, 2012

I spent four years making
Waves of Steel
Hell yes I'm going to turn my avatar into an ad for it.
Fun Shoe
It's been a long time since I looked at the formal definitions of either agile or waterfall, so I'm working off of what I understand them to be rather than what they supposedly actually are. But hey, that's probably what 90% of everyone is doing. So as I understand it, waterfall is basically gather requirements -> create specs -> create design -> implement design, for the entire product all in one fell swoop. Agile is gather minimum requirements -> create specs -> create design -> implement design -> show to clients -> gather new requirements -> specs -> design -> implement, iterate until you run out of money or get bought out.

Like, there's a lot of fluff about user stories, but the core of Agile (again, as I understand it) is that you build a minimum viable product, and then keep looping in the customer so they can see the product as it develops and make certain that what you're building actually solves their needs. The actual process of creating the product uses the same style as waterfall, because you'd be completely insane to try to implement something that doesn't have a well-defined specification and scope. You just do a bunch of small waterfalls instead of one big one.

Bongo Bill
Jan 17, 2012

Neither "agile" nor "waterfall" has a consistent universal definition. They're vague and contextual terms.

VikingofRock
Aug 24, 2008




repiv posted:

Rust Playground allows you to import the most popular crates (which includes itertools) so you can easily peek at the disassembly on there

https://play.rust-lang.org/?gist=95ac417519ad84d133ac7982bc496059&version=stable

I couldn't figure out how to turn on LTO there, which is necessary to get itertools iterators to compile away.

repiv
Aug 13, 2009

VikingofRock posted:

I couldn't figure out how to turn on LTO there, which is necessary to get itertools iterators to compile away.

True, I don't think it's possible to enable LTO on the playground. Nightly Rust somehow manages to compile the iterators away without LTO though :monocle:

taqueso
Mar 8, 2004


:911:
:wookie: :thermidor: :wookie:
:dehumanize:

:pirate::hf::tinfoil:

repiv posted:

Rust Playground allows you to import the most popular crates (which includes itertools) so you can easily peek at the disassembly on there

https://play.rust-lang.org/?gist=95ac417519ad84d133ac7982bc496059&version=stable

Thanks!
Rust code:
#![crate_type = "lib"]

extern crate itertools;
extern crate rand;

use std::iter::IntoIterator;
use itertools::Itertools;

#[no_mangle]
pub fn foo_iter(x: u32, y: u32) -> bool {
    use itertools::Itertools;
    vec![x, y].into_iter().dedup().count() == 1
}

#[no_mangle]
pub fn foo_imperative(x: u32, y: u32) -> bool {
    let mut v = vec![x, y];
    v.dedup();
    v.len() == 1
}


pub fn foo_generic<T, U>(items: T) -> bool
where T: IntoIterator<Item=U>,
      U: PartialEq
{
    items.into_iter().dedup().count() == 1
}

#[no_mangle]
pub fn use_generic(x: u32, y: u32) -> bool {
    let dat = [x, y];
    foo_generic(&dat[..])
}

#[no_mangle]
pub fn use_generic2(dat: [u32; 2]) -> bool {
    foo_generic(&dat[..])
}

#[no_mangle]
pub fn use_generic3(dat: &[u32]) -> bool {
    foo_generic(dat)
}
With nightly:
code:
foo_iter:
	cmp	edi, esi
	sete	al
	ret

foo_imperative:
	cmp	esi, edi
	sete	al
	ret

use_generic:
	cmp	esi, edi
	sete	al
	ret

use_generic2:
	mov	rax, rdi
	shr	rax, 32
	cmp	eax, edi
	sete	al
	ret

use_generic3:
	test	rsi, rsi
	je	.LBB4_1
	cmp	rsi, 1
	jne	.LBB4_3
	mov	al, 1
	ret

.LBB4_1:
	xor	eax, eax
	ret

.LBB4_3:
	lea	rax, [rdi + 4]
	lea	rdx, [4*rsi - 8]
	mov	rcx, rdx
	shr	rcx, 2
	lea	r8d, [rcx + 1]
	and	r8d, 1
	test	rdx, rdx
	je	.LBB4_4
	lea	rsi, [r8 - 1]
	sub	rsi, rcx
	xor	ecx, ecx

.LBB4_6:
	mov	r10d, dword ptr [rax]
	mov	r9d, dword ptr [rax + 4]
	xor	edx, edx
	cmp	r10d, dword ptr [rdi]
	setne	r10b
	je	.LBB4_8
	mov	rdi, rax

.LBB4_8:
	mov	dl, r10b
	add	rcx, rdx
	xor	edx, edx
	cmp	r9d, dword ptr [rdi]
	setne	r9b
	je	.LBB4_10
	lea	rdi, [rax + 4]

.LBB4_10:
	add	rax, 8
	mov	dl, r9b
	add	rcx, rdx
	add	rsi, 2
	jne	.LBB4_6
	test	r8, r8
	je	.LBB4_13

.LBB4_12:
	mov	eax, dword ptr [rax]
	xor	edx, edx
	cmp	eax, dword ptr [rdi]
	setne	dl
	add	rcx, rdx

.LBB4_13:
	test	rcx, rcx
	sete	al
	ret

.LBB4_4:
	xor	ecx, ecx
	test	r8, r8
	jne	.LBB4_12
	jmp	.LBB4_13

taqueso fucked around with this message at 22:06 on Mar 9, 2018

Adbot
ADBOT LOVES YOU

VikingofRock
Aug 24, 2008





Neat! It's cool to see that the Rust compiler can be so aggressive in all these cases, and to see the comparison with the case where it can't be aggressive because it doesn't know the length.

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