Entries:
Comments:
Posts:

Loading User Information from Channel 9

Something went wrong getting user information from Channel 9

Latest Achievement:

Loading User Information from MSDN

Something went wrong getting user information from MSDN

Visual Studio Achievements

Latest Achievement:

Loading Visual Studio Achievements

Something went wrong getting the Visual Studio Achievements

E2E: Herb Sutter and Erik Meijer - Perspectives on C++

Download

Right click “Save as…”

It's not often that we can get two minds of Erik Meijer's and Herb Sutter's caliber together for an impromptu technical conversation during Christmas break at Microsoft... Well, we did and the next hour or so contains a lot of intelligence, knowledge, wisdom, and passion. This is one of the more heated E2Es we've had the pleasure to be a part of and we think you'll agree. Herb and Erik are among the brightest of our trove of bright-minded engineers. We thank Erik and Herb for being so flexible and accommodating (there was no specific topical plan for the conversation other than the obvious—Herb and what he knows so well, C++). 

Herb Sutter is an Architect on the VC++ team, chair of the C++ Standards Committee, a polished technical speaker and a super capable programmer. He is an ardent advocate of native code and works with the industry to move C++ in the direction it needs to go as general purpose computing evolves. As you know, Erik Meijer is a functional programming fundamentalist, a C9 celebrity, a master of mathematical duality and an unusually productive innovator (LINQ, "Volta," and Rx, are a few of his recent accomplishments). Erik is also the Chief Interrogation Officer for C9's Expert to Expert series. In this case, given functional programming's conceptual fingerprint showing up in almost all general purpose programming languages, including C++ with the addition of lambdas, putting Erik and Herb in the same room was sure to create some geeky technical magic. This post captures exactly what happened, unedited and raw. It's one of the best E2Es to date! Thank you, Erik and Herb! Keep pushing the envelope.

Tune in. Enjoy. Learn.

Tags:

Follow the Discussion

  • This is going to completely ROCK!!!  Downloading now...

     

  • Bent Rasmussenexoteric stuck in a loop, for a while

    I like Erik's comment on futures - kind of like "how far down the rabbit hole do you want to go" - like violence, if one iteration or recursion doesn't work, just recurse or iterate some more ;~) Calling a method on a future returns another future, a beautiful solution. A purist has to object a little to the mutable nature of plain futures though.

    On the beauty of compile-time function evaluation and reflection, the language D (in particular D 2.0) has to be mentioned. As a refactored C++ it has a lot to offer in this space.

    Finally, what to alias Erik and Herb? Why top (⊤, Erik) and bottom (⊥, Herb) of course! And here, the ends meet.

    C++ is not for me but I still envy the efficiency and expressiveness of templates.

    Speaking of efficiency, can't wait to hear more on Phoenix.

    Great interview Smiley

  • felix9felix9 the cat that walked by itself

    Too good for WMP ? I try to open those two WMV links in WMP12 on Win7, WMP says its not supported and cant play, then WMP crashed ...... Perplexed

    the Silverlight player works though.

    EDIT: I started WMP directly without open links, it displayed a message: 'update completed', now WMP can play those WMVs as usual.

    turns out, Windows Update installed an update of MediaFoundation (KB2454826) yestoday, it looks like, WMP should be started at least once after this update, to work properly. Expressionless

    now enjoy this episode Smiley

  • An excellent E2E dialogue!

  • Eric AguiarHeavens​Revenge Know Thyself

    As I watch the video I'll jot down points I'd like to mention, time to enjoy 2 of my favourite speakers talk about my 2nd favourite language Big Smile C++0x:

    I'm glad Erik done his usual and started picking apart static auto type inference instead of just trying to rush towards lambdas Smiley The level on which subjects get explorerd is a unique trait of the Expert 2 Expert series, and I value this trait very highly.
    WOO I'm exceedingly happy that STL shall be having a new advanced STL series in the medium future from now.And considering how STL says his own last name, its sort of sounds like lao-oo-aide, far from its spelling Tongue Out.
    Erik, I'm telling you, I LOVE Haskell, it is my #1 favourite language, but happly admit with pride that C++ is my 2nd favourite/used language, and I highly encourage you to have a good healthy serious look at C++0x specifically, not the old standard.
    You may be trying to keep too firm a grasp on those pesky VB/C# since you had such an influence in their creation and evolution Wink

    Herb you are awesome, and thank you for making C++0x what it is today by making excellent design decisions on the comitee.
    PS we need a std::thread library implementation integrated into what the PPL has been developed as, and please consider VC2010SP1 to also feature uniform initialization syntax next Tongue Out

    Thank you again Charles!! 

  • felix9felix9 the cat that walked by itself

    what about C++/CLI ? is it stucked in a 'snapshot' ? can we use c++ lambda syntax to construct CLR delegates ???

  • Dave Williamsondavewill here birdie birdie, get in my belly!

    Erik mentioned a lot of times wanting to declare an interface inline.  Something like New IFOO.  What benefit is there to declaring an inline interface if the lifetime of the interface would be finite (limited to the function)?

  • @davewill:

    These should have the same mechanism for capturing free variables from the enclosing scope as lambdas. 

    It seems so obvious to me, that object-oriented languages have closures for objects. 

  • I watched this video only because Herb Sutter was in it but this time i got disappointed by the content. The fact that Erik Meijer was in it only made the video worse since for some strange reason i really dislike him. Probably because he's a bad speaker ex. saying A LOT of "You know". Erik Meijer demonstrates quite well why things like "You know" should be avoided. (Short answer: It's annoying! ) @Charles: I'm telling you this so you can make better videos in the future. Hopefully with more Herb Sutter and C++0x and far less "You know" when Erik Meijer is around. By the way: We were promised a lot of c++ videos this year, are there any plans on holding that promise ? ( This video doesn't count )
  • Oh great, now that formatting bug affects logged in users as well, nice job! Or was this another "by design" "feature" ? Feedback stings doesn't it ? Well fix the problem then, already, please! Btw: where did the text formatting toolbar go ?
  • WhatWouldBukowskiDoWhatWould​BukowskiDo

    Great video. Probably the best on channel9.
    Charles, Please get Herb Sutter to do more of these informal interviews. Bribe him with whatever he was drinking if you have too. The C++ community desperately needs guides like him in this post-sequential world. Popularizing C++0x idioms is important to do while there is still some hype to it. So that C++0x can avoid the fate of c++98 where most c++ programmers (in my experience) still don't use it. 
    (Even if I'm not a fan of C#. I enjoy Eric's videos also, especially the ones about functional programming.)
    Cheers

  • @Mr Crash: Cheers!

  • CharlesCharles Welcome Change

    @Mr Crash: Whatever.... Troll somewhere else

    C

  • Eric AguiarHeavens​Revenge Know Thyself

    Well if you plan on having some extremely technical and in-depth C++ conversations occur, may I suggest the two speakers which might actually be able to augment and pick apart eachothers brains?

    My two C++ Expert 2 Expert candidates which you could pair with Herb Sutter are: Don McCrady or Rick Molloy. Both of which are awesome and whom I respect for C++ conversation.

    If not Erik, which isn't exactly bad, but I must aggree he is a little too engrained in the managed language world these days, unless having 2 different views are more helpful for one to ask the other relevcant questions insstead of having both as native C++ pro's?

    What do you fellow 9er's think may be a good pairing for C++0x topics if they are available to speak to??

  • CharlesCharles Welcome Change

    @WhatWouldBukowskiDo: Will do. There will be a focus on C++0x and more in '11 on 9. Stay tuned.

    C

  • CharlesCharles Welcome Change

    @HeavensRevenge:the idea behind e2e is experts in similar domains or different ones... It doesn't really make sense to have experts from the same team. That's not the point of this. Also, Erik is functional more than .NET...

  • @head.in.the.box: Hi

     

    @Charles: Aren't you a bit too old for misusing the word "troll" or is it that you don't know the correct definition of the word ?

    So is it now that all that come with constructive criticism are trolls ?

    Well that's childish and immature. You should learn to use the feedback you get, grow up already!

     

    The least you could do is thank me for spending me time writing to you and coming with suggestions of how to improve things.

    Sigh, some people just don't get it no matter how many different ways you describe it to them, you got to wonder if something is missing or not working correctly.

  • Eric AguiarHeavens​Revenge Know Thyself

    @Charles: I suppose it depends if the "Expert" is always going to be Erik. I'm just fine with Erik as my name being "Eric" I feel a connction to the conversation in addition to many other reasons, just suggesting Tongue Out. But was wasn't sure whether experts from separate domains were close to a requirement for you. If Erik isn't the only candidate to be the Expert asking the deep technical product questions along with you, anyone on the CLR or BCL team would be pretty cool to have.  Depending on how managed Joe Duffy is,personally I think he'd be pretty cool to join in on the fun again Big Smile I miss his good conversation on C9, he was also a very functional guy which saw eye-to-eye with Erik on many things when not being limited by product release work.
    I don't exactly care who speaks on camera so long as the super awesome C++0x content on C9 gets some attention and exploration Big Smile

    @Mr Crash: I must say I notice you having mostly negative stuff to say, you are definitely walking on the edge of trolling a little bit.  I'm sure theres other ways in which you could word the feedback/comment to actually have them consider your words of advise instead of writing your comment off and disconcern it.

  • CharlesCharles Welcome Change

    @Mr Crash:  Please read our Doctrine. Comments on this post should remain focused on the myriad of software engineering topics discussed in the video. Personal attacks in any form are not welcome here.

    fork->end();

    C

    PS: Post-Edited by Charles to remove my jerky comments.

  • I'm not sure that the presence of InterlockedIncrement effectively refutes Erik's argument that Actors are a NOT good substitute for expressing mutability (or other higher-level state interactions) in the type system. Let's get more of this functional goodness baked (tie-dyed?) into the CTS & BCL, please? Wink

  • William Staceystaceyw Before C# there was darkness...

    Good one. Erik, MrCrash is crazy, your the best.

    I do think there is still more discussion to be had on the x= x + 1 problem Erik mentioned on Actor pattern. Do you solve it via convention, static rules, or some other way? Guess would need to list all the use cases and sticky points and toss spegetti at it.

    On the Future object deal. I think Erik mentioned before, that when it is future or async, you Need to see the difference so your not back in RPC world which leads the programmer down a path where everything looked local, but is not.  So I think explict difference can be good here. However, I see where that abstraction could be good also.  Maybe there is still a middle ground not seen yet.

  • , staceyw wrote

    I do think there is still more discussion to be had on the x= x + 1 problem Erik mentioned on Actor pattern. Do you solve it via convention, static rules, or some other way? Guess would need to list all the use cases and sticky points and toss spegetti at it.

    From what I've understood is that Herb suggests that you design your API in such a way that it allows your users to express as much as possible in a single call or message. In the x=x+1 example, you don't want the user to first send a message to get x, compute the new value of x and then send the new value of x back to the actor. It's probably preferable to have the user use only one message in total to update x. You could think of an "IncrementX" message, or perhaps more generally, a "ModifyX" message which contains a lambda**.

    (** Hmm... are C++0x lambdas serializable?)

  • William Staceystaceyw Before C# there was darkness...

    I think Erik talked about remoteable linq and lambda before, but not heard anything.

    Got me thinking, that could possibly solve the getter/setter property thing.  Getter/setters could only be accessed via a func call so they would be safe on the single threaded Actor.  It would also be a way sync multiple steps (actor method calls, property updates, actor blocking operation, etc) in single atom operation.  You can not predict or write every possible api someone would need, so you need something like that anyway.  A generic kind of Rest/ADO Data update/query on Actors objects.  Actually, Astoria is similar to the model we are talking about.

    actor.Run(()=>
    {
        // Public X only settable via a lambda.
        actor.X = actor.X + 1;
    });
    
    // Run() is a some special function avalable on all Actors.

  • Bent Rasmussenexoteric stuck in a loop, for a while

    I must say that, as a compiled language and in the research perspective of verified operating systems, by means of typed assembly language (proof carrying code), C++ is not entirely irrelevant, at least on its path towards higher-level functional, perhaps even quasi-purist, or effect-constraining constructs, where it aquires some of the virtues of more fundamentalist languages; but I guess a more appropriate term would be multi-paradigm.

    @Erik: you've talked about, taught us about and teased us about fundamentalist functional programming and we've seen slides about it in the context of .Net, so: any chance you can reveal more to us about the your monadic purist world-takeover plans in the context of or outside the context of .Net, excluding Haskell which is conquered territory?

    @ShinNoNoir: doesn't that conflict with the command-query principle: don't do and ask at the same time.

    @Charles: slam dunk.

  • @staceyw: I guess the point Eric was making is that if you start doing that sort of stuff you've just reinvented locks again (on top of actors, but still). You either get races, or deadlocks. Also, this kind of lock is probably less efficient because it's layered on top of another abstraction.

    Actors might help enable some by exposing latent concurrency, but it does nothing to improve safety. It's still just as tedious, error-prone and above all manual as it ever was.

  • CharlesCharles Welcome Change

    Keep on thinking. Love the ideas here, Niners. For the fundamentalist functional programming stuff, maybe we can convince Erik to spin up a new lecture series Smiley

    Dr. Meijer?
    C

  • William Staceystaceyw Before C# there was darkness...

    Had a even better idea. The actor framework exposes Read() and Write() methods to every actor.  The actor maintains a RW lock internally via a r/w scheduler.  All properties must be accessed via Read or Write methods and not directly.  The framework will pass either a read actor reference or a Write reference to the lambda as needed.  A read reference can't be cast to a write interface, etc.  With a Read reference object, you can only call Read safe methods and properties.

    Task<int> t = actor.Read((readRef)=>
    {
         return readRef.X + readRef.Y;
         // Writes not allowed:
         // readRef.UpdateSome(true, 5); // Not even exposed.
    });
    
    Task<int> t = actor.Write((writeRef)=>
    {
        // I have a write lock inside this lamda to the Actor.
        int i = writeRef.X;
        i = i + writeRef.Y;
        return writeRef.UpdateZ(i); // Write methods exposed.
    });
    
    

    So class may look like:

    public class MyActor : Actor
    {
        //public Task Read(Func<ActorReader, Task>); // from base.
        //public Task Write(Func<ActorWriter, Task>);
        public int X {get{return x;} set{x = value;}} // Properties only accessable via Read/Write functions above.
        
        [WriterMethod]
        public int UpdateCount(int i);
    
        [ReaderMethod]
        public int GetCount();
        
        //...
    }

    So in this way, multiple readers can run concurrently and writers are scheduled between read groups.  My lambda code never has to deal with any lock logic.  The framework can do runtime check and throw if trying to Write inside a Reader lamda. Maybe could even do compile time check.  You adorn Methods with "Write" attributes if the method updates internal state.  Otherwise, the method is assumed to be read only and must not modify internal invariants.  So I think this would solve Erik's issue with Races on properties.  I guess you could take it a step farther and say public methods are only Helpers and just codify some operation you could do yourself with a Read()/Write() lamda.  Maybe even say all methods must use properties and not be able to change private vars. That way, you have only 1 write channel and leverage that.

    It also means you have 1 spot to handle rollback if runtime made Write() transactional. If a lamda throws, the runtime just does a rollback to the Entry state before the call.  That means nested graphs would just work also in a call graph. Exceptions just perk to the top and are exposed in your Task<T> future.

  • @HeavensRevenge: If you are talking about my first comment on this page, then i'm not sure how to improve it. If you beat around the bush too much people will not get what you are saying and just ignore you. On the other hand if you are friendly but direct then people will understand. But perhaps i'm too direct

    ( I know by experience that positive feedback is not that helpful, when i read through the feedback e-mails i find it in general that negative feedback is more helpful to me, sure positive feedback is also helpful but not as much as negative feedback. )

    @Charles:

    1. You started it by calling me a troll. ( So i had to defend myself, of course )

    Instead of calling me a troll you could have asked me to elaborate on what ever you had a problem with. Now that is called communication. 

    2. I have not attacked you personally not even close and nor will i ever do it unless _extremely_ provoked.

    3. I have read it and i re-read today, now that i think about it channel 9 have broking the Doctrine  several times. For example 1. You yourself broke it by calling me a troll instead of accepting my feedback.  2. "Marketing has no place on Channel 9" need i say more?

    That said, i agree, this is not the place for this discussion. I will assume you have my e-mail address so if you want to continue this discussion then use it.

    fork->end()    // I will assume this means 'end of off-topic discussion'

     

  • William Staceystaceyw Before C# there was darkness...

    Just stick to the tech. Nobody cares about other opinions.

  • CharlesCharles Welcome Change

    @Mr Crash: It's not that you are too direct... It's that your approach to delivery of feedback is overtly unfriendly. My apologies for the troll comment (to be precise, I asked that you do not troll on these threads, which is not exactly the same thing as calling you a troll, but the inference is logical).

    You are right about the meaning of fork->end();.

    C

  • Eric AguiarHeavens​Revenge Know Thyself

    I keep re-watching this since its nice hearing Herb Sutter speak in a converesation more than in a presentation setting infront of a huge audience like at PDC or the many previous presentations I've heard him deliver.

    It's sort of funny because I still am in love with my 1st language Tongue Out My 1st language I learnt was C++ before backtracking into C to learn why C++ was needed and why classes were created from the creators point-of-view.
    (I dont consider VisualBasic as my 1st language since I had a very weird discovery -> hate relationship with it in grade 3-4 by doing the classical typing code from pages of books to make completely useless games/programs after hours of typing lol)

    @staceyw: Yes indeed if you limit usage by proper API design, in any language it's easy to constrain usage to only safe usage Tongue Out the real trick is allowing both power AND correct usage of the abstraction.

  • Steve RobbFuz

    Great interview, but Herb makes a surprising mistake around 19 minutes in.  They're talking about this kind of construct:

    template <typename T>
    class C : public T
    {
    };

    ... and Herb refers to it as the Curiously Recurring Template Pattern.  The CRTP actually looks like this:

    class C : Base<C>
    {
    };

    What they are talking about is a Parameterised Base Class:

    http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Parameterized_Base_Class

    ('C<T> inherits T' vs 'C inherits T<C>')

  • WhatWouldBukowskiDoWhatWould​BukowskiDo

    @ssylvan. The point is that you can design away some potential deadlocks or races, by making your interface more high level and coarse grained. That way the library implementer can take care of internal low level synchronization and the user can take care of high level synchronization, instead of the user being forced to take care of both. Having a for_each type interface is much better than having a interface that the user calls in a loop. In the first case the library has control over how iteration and synchronisation is done, in the second it has none.
    In this sense dealing with high actors is much better than dealing with low level locks.
    Herb wrote an article about this very topic: 
    http://herbsutter.com/2010/07/12/effective-concurrency-prefer-using-active-objects-instead-of-naked-threads/

  • William Staceystaceyw Before C# there was darkness...

    @staceyw: Yes indeed if you limit usage by proper API design, in any language it's easy to constrain usage to only safe usage Tongue Out the real trick is allowing both power AND correct usage of the abstraction.

    Yes. I am not sure this solution gets us 100% there, but is powerful (allows arbitrary lamba code) and is safe (orders access to state in a sane way). It also would seem to lead down a correct-by- construction path I think. Some details to work out, but think it can work in general and smells nice.

  • @WhatWouldBukowskiDo: But that has nothing to do with actors. You can do the same coarse-grained API-design with locks or synchronized methods too. Like I said, actors may expose more parallellism (because they run on their own lightweight thread), but they don't improve correctness. At the end of the day it's just locks in a different form.

    I'd also somewhat disagree with the API suggestion, actually.

     

    In a single-threaded scenario it's generally regarded better to have a few generic methods that can be easily composed to do fifty things, than have fifty "big" methods (i.e. the API should be "minimal and complete"). It's only when you bring in locking that you need to specialize and pull things together into "bigger" methods so that you can carefully manage locking for some common tasks. That may well be the best strategy on balance when you do have to worry about locking, but it's at least worth noticing that you're going against normal guidelines for good API-design when doing so, which indicates that the concurrency model has some room to improve.

    Ideally we could still use a "minimal and complete" API design that affords composability, while maintaining thread safety. This is, for example, what STM is designed to solve.

  • NovoxNovox “Simplicity is the ultimate ​sophisticat​ion.” —Leonardo da Vinci

    @Fuz: That seems to make sense, indeed. I was a little confused about this answer, but as I am not a C++ expert I swallowed it Wink A collegue of mine implemented a OO wrapper around BLAS/LAPACK and he used CRTP for static polymorphism, IIRC (http://flens.sourceforge.net/); so I was wondering how CRTP can provide support for mixins. "Parameterised Base Class" looks like the right pattern.

  • madhumadhu

    Excellent interview. Looking for more convesation with Herb Sutter on various topics.
     

  • John Melville-- MDJohn Melville-- MD Equality Through Technology

    In reply to DaveWill's questiom about why you would want to be able to create anonymous interface implementations.

    Please notice that the C# iterator pattern is almost exactly trat -- it lets you create an anoymous IEnumerable in line.  Imagine being able to do the same thing for arbitrary interfaces.

  • alirazaliraz

    I am actually somewhat disappointed by this talk. I was expecting Erik to ask some crucially interesting questions about connections between Haskell algebraic data types and C++ templates. Also possibly about Haskell type classes and C++ features that enable emulating behavioral specification on templates, e.g., template template params.
    Another topic that could have been interesting but was not even mentioned was the "kind safety" of type-level programming in C++ vs. what can be done in Haskell with GADT.

  • @davewill: As others have indicated I think Erik wasn't talking about being able to define inline interfaces as much as being able to create inline implementations.  Imagine a method call that requires an IFoo object and being able to define an implementation and pass an instance all in a single code block.  Here's some fantasy C#:

    obj.DoThat( new IFoo {
      public int doA() { return 1; }
      public int doB() { return 2; }
    });
    

  • , avranju wrote

    @davewill: As others have indicated I think Erik wasn't talking about being able to define inline interfaces as much as being able to create inline implementations.  Imagine a method call that requires an IFoo object and being able to define an implementation and pass an instance all in a single code block.  Here's some fantasy C#:

     

    1
    2
    3
    4
    obj.DoThat( new IFoo {
      publicintdoA() { return1; }
      publicintdoB() { return2; }
    });

    This feature is in F# now, by the way.

  • PhilhippusPhilhippus

    A great lively and honest discussion between two technical titans. The value of this type of thing is immense. Keep doing what you're doing!

  • zurazura

    [quote]
    Jan 16, 2011 at 1:10 PM, Charles wrote
    ... For the fundamentalist functional programming stuff, maybe we can convince Erik to spin up a new lecture series  Dr. Meijer?C

    [/quote]
    That would be great.
    Maybe more advanced (with more theory) Haskell lectures would be natural continuation?
     Zura

  • CharlesCharles Welcome Change

    @zura: I'm trying to convince Erik to do a lecture series on category theory. He's so busy that I won't guarantee that this will happen, but I will continue to pester him until he commits or no longer returns my email and phone calls Smiley

    C

  • zurazura

    @Charles: Umm, fingers crossed.. :)

  • CharlesCharles Welcome Change

    @zura: Erik's in! Smiley This will be excellent!!! Thank you, Erik Smiley
    C

  • zurazura

    @Charles:
    Great!!! I was sure but didn't expected it to happen so soon :)
    Thank you and Erik!

    Zura

  • HenrikHenrik

    @Charles: That's really awesome!!! More Erik please!!!

  • David GrenierDavid Grenier

    Epic@43:00
     
    I really hang on Erik's point at 46:50 because after coding (what I believe is) an elegant non-brute-force solution to Project Euler's problem 11:
     

    let exec (data : string) = let maxMatch dic = let getOrZero c = defaultArg (Map.tryFind c dic) 0 let maxLine (iRatio, jRatio) = let lineValue (KeyValue((i, j), v)) = v * getOrZero (i + iRatio, j + jRatio) * getOrZero (i + iRatio * 2, j + jRatio * 2) * getOrZero (i + iRatio * 3, j + jRatio * 3) let max = dic |> Seq.map lineValue |> Seq.tryFind (fun x -> x <> 0) defaultArg max 0 [(0, 1); (1, 0); (-1, 1); (1, 1)] |> Seq.map maxLine |> Seq.max data.Split('\n') |> Seq.mapi (fun i -> fun line -> line.Split(' ') |> Seq.mapi (fun j -> fun v -> ((i, j), int v))) |> Seq.concat |> Seq.sortBy (fun (_, v) -> -v) |> (Map.empty<_, _> |> Seq.scan (fun d -> fun e -> d.Add e)) |> Seq.map (fun d -> maxMatch d) |> Seq.find (fun v -> v <> 0)

     
    I later realized there was no way to parallelize it, because it's inherentily sequential and as such I was a bit disapointed on the promise of easily parallelizable code through functionnal programming.

  • David GrenierDavid Grenier

    [code]
    let exec (data : string) =
    let maxMatch dic = let getOrZero c = defaultArg (Map.tryFind c dic) 0 let maxLine (iRatio, jRatio) = let lineValue (KeyValue((i, j), v)) = v * getOrZero (i + iRatio, j + jRatio) * getOrZero (i + iRatio * 2, j + jRatio * 2) * getOrZero (i + iRatio * 3, j + jRatio * 3) let max = dic |> Seq.map lineValue |> Seq.tryFind (fun x -> x <> 0) defaultArg max 0 [(0, 1); (1, 0); (-1, 1); (1, 1)] |> Seq.map maxLine |> Seq.max data.Split('\n') |> Seq.mapi (fun i -> fun line -> line.Split(' ') |> Seq.mapi (fun j -> fun v -> ((i, j), int v))) |> Seq.concat |> Seq.sortBy (fun (_, v) -> -v) |> (Map.empty<_, _> |> Seq.scan (fun d -> fun e -> d.Add e)) |> Seq.map (fun d -> maxMatch d) |> Seq.find (fun v -> v <> 0)
    [/code]
     
    :(

  • CharlesCharles Welcome Change

    opening comments again...

    C

Remove this comment

Remove this thread

close

Comments Closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums,
or Contact Us and let us know.