LINQ is fun!
-
Functional programming )))
stepan hakobyan wrote:
Functional programming )))
Yes! That was the point of the experiment.
Latest Articles:
Client-Side Type-Based Publisher/Subscriber, Exploring Synchronous, "Event-ed", and Worker Thread Subscriptions -
(serious) Is there a reason to write ugly code like that ? Is it more efficient ? If I was looking at code like that I would probably send it back after code review. :confused:
I'd rather be phishing!
Maximilien wrote:
Is there a reason to write ugly code like that ?
I was curious to what extent, ok, extreme, I could go. One of the things I love about functional programming is the pipe operators |> and <| which have no equivalent in C#, the best one can do is the dot operator. So I wanted to play with the concept, see how far I could take it, what extension methods I needed to create to maintain the "continuation", how hard it would be to debug, and if the result looked in any way maintainable. One of the things I discovered is that, as usual, wrapping simple things like "where" expressions into a named extension method improves readability but potentially decreases the "well, how is that actually accomplished" immediate comprehension, and naming can be quite difficult when creating bizarre functions that iterate over a collection and pass in both the collection item and some other pre-computed value. So consider it a "thought experiment" in actual implementation. ;)
Latest Articles:
Client-Side Type-Based Publisher/Subscriber, Exploring Synchronous, "Event-ed", and Worker Thread Subscriptions -
I read it aloud and accidentally summoned and eldritch horror. Please provide the unsummon chant.
GCS d--(d+) s-/++ a C++++ U+++ P- L+@ E-- W++ N+ o+ K- w+++ O? M-- V? PS+ PE- Y+ PGP t+ 5? X R+++ tv-- b+(+++) DI+++ D++ G e++ h--- r+++ y+++* Weapons extension: ma- k++ F+2 X
den2k88 wrote:
Please provide the unsummon chant.
You really do not want to see the one-liner for that! It summons several other beasts to defeat the eldritch horror, then you have those beasts to contend with, which requires summoning more beasts -- recursive stack overflow exception!
Latest Articles:
Client-Side Type-Based Publisher/Subscriber, Exploring Synchronous, "Event-ed", and Worker Thread Subscriptions -
Especially when combined with extension methods and fluent-style methods.
envvars
.Municipalities()
.Select(m => m.Fixups())
.NotServiceAccess()
.Where(m => m.VerifyConnection(_ => Log($"{m.Municipality}: {m.ConnectionString} => Connection failed.")))
.Do(munis =>
munis.SelectWith(m => M5.GetTableNames(AUDIT_SCHEMA, m.ConnectionString), (m, with) => (auditableEntities.NotIn(with, s => s.TableName.ToLower(), t => t.ToLower()), m))
.ForEach(q => q
.Iterate((t, m) =>
t
.Do(_ => Log($"{m.Municipality}: {t.TableName} => Audit table missing"))
.GenerateMissingAuditTableSql(m)
.Execute(m.ConnectionString, (sql, e) => Log($"{m.Municipality}: {t.TableName} => {e.Message}\r\nFailed to execute SQL: {sql.ToString()}"))
)))
.Do(munis =>
{
munis.SelectWith(m => M5.GetTableNames(AUDIT_SCHEMA, m.ConnectionString), (m, with) => (auditableEntities.In(with, s => s.TableName.ToLower(), t => t.ToLower()), m))
.ForEach(q => q
.Iterate((t, m) =>
{
Log($"{m.Municipality}: {t.TableName} => Checking...");
var entityColumns = M5.GetColumnList(DBO_SCHEMA, m.ConnectionString, t.TableName);
var auditColumns = M5.GetColumnList(AUDIT_SCHEMA, m.ConnectionString, t.TableName);entityColumns.NotIn(auditColumns, s => s.Name.ToLower(), f => f.Name.ToLower()) .DoIf(q2 => q2.Count() > 0, q3 => Log($" {q3.Count()} missing fields")) .ForEach(f => { Log($" {m.Municipality}: {t.TableName} => Field {f} missing in audit table"); f .GenerateMissingColumnSql(m, AUDIT\_SCHEMA, t.TableName) .Execute(m.ConnectionString, (sql, e) => Log($"{m.Municipality}: {t.TableName} => {e.Message}\\r\\nFailed to execute SQL: {sql.ToString()}")); }); })); });
This is a custom "one line" function that creates missing audit tables or adds the missing columns that the entity defines but someone forgot to add to the audit table. :-D
Latest Articles:
Client-Side Type-Based PublishWhy? Who hurt you? :-D
-
Especially when combined with extension methods and fluent-style methods.
envvars
.Municipalities()
.Select(m => m.Fixups())
.NotServiceAccess()
.Where(m => m.VerifyConnection(_ => Log($"{m.Municipality}: {m.ConnectionString} => Connection failed.")))
.Do(munis =>
munis.SelectWith(m => M5.GetTableNames(AUDIT_SCHEMA, m.ConnectionString), (m, with) => (auditableEntities.NotIn(with, s => s.TableName.ToLower(), t => t.ToLower()), m))
.ForEach(q => q
.Iterate((t, m) =>
t
.Do(_ => Log($"{m.Municipality}: {t.TableName} => Audit table missing"))
.GenerateMissingAuditTableSql(m)
.Execute(m.ConnectionString, (sql, e) => Log($"{m.Municipality}: {t.TableName} => {e.Message}\r\nFailed to execute SQL: {sql.ToString()}"))
)))
.Do(munis =>
{
munis.SelectWith(m => M5.GetTableNames(AUDIT_SCHEMA, m.ConnectionString), (m, with) => (auditableEntities.In(with, s => s.TableName.ToLower(), t => t.ToLower()), m))
.ForEach(q => q
.Iterate((t, m) =>
{
Log($"{m.Municipality}: {t.TableName} => Checking...");
var entityColumns = M5.GetColumnList(DBO_SCHEMA, m.ConnectionString, t.TableName);
var auditColumns = M5.GetColumnList(AUDIT_SCHEMA, m.ConnectionString, t.TableName);entityColumns.NotIn(auditColumns, s => s.Name.ToLower(), f => f.Name.ToLower()) .DoIf(q2 => q2.Count() > 0, q3 => Log($" {q3.Count()} missing fields")) .ForEach(f => { Log($" {m.Municipality}: {t.TableName} => Field {f} missing in audit table"); f .GenerateMissingColumnSql(m, AUDIT\_SCHEMA, t.TableName) .Execute(m.ConnectionString, (sql, e) => Log($"{m.Municipality}: {t.TableName} => {e.Message}\\r\\nFailed to execute SQL: {sql.ToString()}")); }); })); });
This is a custom "one line" function that creates missing audit tables or adds the missing columns that the entity defines but someone forgot to add to the audit table. :-D
Latest Articles:
Client-Side Type-Based Publish -
Especially when combined with extension methods and fluent-style methods.
envvars
.Municipalities()
.Select(m => m.Fixups())
.NotServiceAccess()
.Where(m => m.VerifyConnection(_ => Log($"{m.Municipality}: {m.ConnectionString} => Connection failed.")))
.Do(munis =>
munis.SelectWith(m => M5.GetTableNames(AUDIT_SCHEMA, m.ConnectionString), (m, with) => (auditableEntities.NotIn(with, s => s.TableName.ToLower(), t => t.ToLower()), m))
.ForEach(q => q
.Iterate((t, m) =>
t
.Do(_ => Log($"{m.Municipality}: {t.TableName} => Audit table missing"))
.GenerateMissingAuditTableSql(m)
.Execute(m.ConnectionString, (sql, e) => Log($"{m.Municipality}: {t.TableName} => {e.Message}\r\nFailed to execute SQL: {sql.ToString()}"))
)))
.Do(munis =>
{
munis.SelectWith(m => M5.GetTableNames(AUDIT_SCHEMA, m.ConnectionString), (m, with) => (auditableEntities.In(with, s => s.TableName.ToLower(), t => t.ToLower()), m))
.ForEach(q => q
.Iterate((t, m) =>
{
Log($"{m.Municipality}: {t.TableName} => Checking...");
var entityColumns = M5.GetColumnList(DBO_SCHEMA, m.ConnectionString, t.TableName);
var auditColumns = M5.GetColumnList(AUDIT_SCHEMA, m.ConnectionString, t.TableName);entityColumns.NotIn(auditColumns, s => s.Name.ToLower(), f => f.Name.ToLower()) .DoIf(q2 => q2.Count() > 0, q3 => Log($" {q3.Count()} missing fields")) .ForEach(f => { Log($" {m.Municipality}: {t.TableName} => Field {f} missing in audit table"); f .GenerateMissingColumnSql(m, AUDIT\_SCHEMA, t.TableName) .Execute(m.ConnectionString, (sql, e) => Log($"{m.Municipality}: {t.TableName} => {e.Message}\\r\\nFailed to execute SQL: {sql.ToString()}")); }); })); });
This is a custom "one line" function that creates missing audit tables or adds the missing columns that the entity defines but someone forgot to add to the audit table. :-D
Latest Articles:
Client-Side Type-Based PublishStill too many ";"
-
(serious) Is there a reason to write ugly code like that ? Is it more efficient ? If I was looking at code like that I would probably send it back after code review. :confused:
I'd rather be phishing!
-
Especially when combined with extension methods and fluent-style methods.
envvars
.Municipalities()
.Select(m => m.Fixups())
.NotServiceAccess()
.Where(m => m.VerifyConnection(_ => Log($"{m.Municipality}: {m.ConnectionString} => Connection failed.")))
.Do(munis =>
munis.SelectWith(m => M5.GetTableNames(AUDIT_SCHEMA, m.ConnectionString), (m, with) => (auditableEntities.NotIn(with, s => s.TableName.ToLower(), t => t.ToLower()), m))
.ForEach(q => q
.Iterate((t, m) =>
t
.Do(_ => Log($"{m.Municipality}: {t.TableName} => Audit table missing"))
.GenerateMissingAuditTableSql(m)
.Execute(m.ConnectionString, (sql, e) => Log($"{m.Municipality}: {t.TableName} => {e.Message}\r\nFailed to execute SQL: {sql.ToString()}"))
)))
.Do(munis =>
{
munis.SelectWith(m => M5.GetTableNames(AUDIT_SCHEMA, m.ConnectionString), (m, with) => (auditableEntities.In(with, s => s.TableName.ToLower(), t => t.ToLower()), m))
.ForEach(q => q
.Iterate((t, m) =>
{
Log($"{m.Municipality}: {t.TableName} => Checking...");
var entityColumns = M5.GetColumnList(DBO_SCHEMA, m.ConnectionString, t.TableName);
var auditColumns = M5.GetColumnList(AUDIT_SCHEMA, m.ConnectionString, t.TableName);entityColumns.NotIn(auditColumns, s => s.Name.ToLower(), f => f.Name.ToLower()) .DoIf(q2 => q2.Count() > 0, q3 => Log($" {q3.Count()} missing fields")) .ForEach(f => { Log($" {m.Municipality}: {t.TableName} => Field {f} missing in audit table"); f .GenerateMissingColumnSql(m, AUDIT\_SCHEMA, t.TableName) .Execute(m.ConnectionString, (sql, e) => Log($"{m.Municipality}: {t.TableName} => {e.Message}\\r\\nFailed to execute SQL: {sql.ToString()}")); }); })); });
This is a custom "one line" function that creates missing audit tables or adds the missing columns that the entity defines but someone forgot to add to the audit table. :-D
Latest Articles:
Client-Side Type-Based PublishThere is a module for using actual, real SQL statements in code, rather than LINQ. I had to use it once for ad hoc sorting, because LINQ was way too cumbersome. Too bad the LINQ creators couldn't incorporate it.
-
Maximilien wrote:
Is there a reason to write ugly code like that ?
I was curious to what extent, ok, extreme, I could go. One of the things I love about functional programming is the pipe operators |> and <| which have no equivalent in C#, the best one can do is the dot operator. So I wanted to play with the concept, see how far I could take it, what extension methods I needed to create to maintain the "continuation", how hard it would be to debug, and if the result looked in any way maintainable. One of the things I discovered is that, as usual, wrapping simple things like "where" expressions into a named extension method improves readability but potentially decreases the "well, how is that actually accomplished" immediate comprehension, and naming can be quite difficult when creating bizarre functions that iterate over a collection and pass in both the collection item and some other pre-computed value. So consider it a "thought experiment" in actual implementation. ;)
Latest Articles:
Client-Side Type-Based Publisher/Subscriber, Exploring Synchronous, "Event-ed", and Worker Thread SubscriptionsIMO the biggest problem with overly complex linq is that it's all one statement to the debugger. If you to step from one
.
to the next being able to view the data being passed around without having to spam replace each.
with;\r\n foo =
and turning anonymous functions into normal ones (and of course undoing all of that when done) troubleshooting would be much easier.Did you ever see history portrayed as an old man with a wise brow and pulseless heart, weighing all things in the balance of reason? Is not rather the genius of history like an eternal, imploring maiden, full of fire, with a burning heart and flaming soul, humanly warm and humanly beautiful? --Zachris Topelius Training a telescope on one’s own belly button will only reveal lint. You like that? You go right on staring at it. I prefer looking at galaxies. -- Sarah Hoyt
-
I read it aloud and accidentally summoned and eldritch horror. Please provide the unsummon chant.
GCS d--(d+) s-/++ a C++++ U+++ P- L+@ E-- W++ N+ o+ K- w+++ O? M-- V? PS+ PE- Y+ PGP t+ 5? X R+++ tv-- b+(+++) DI+++ D++ G e++ h--- r+++ y+++* Weapons extension: ma- k++ F+2 X
say:
oh
wa
tagu
sigh
amten times as fast as you can. if that doesn't work, try
me
we
todd
edinstead. /trollface
Did you ever see history portrayed as an old man with a wise brow and pulseless heart, weighing all things in the balance of reason? Is not rather the genius of history like an eternal, imploring maiden, full of fire, with a burning heart and flaming soul, humanly warm and humanly beautiful? --Zachris Topelius Training a telescope on one’s own belly button will only reveal lint. You like that? You go right on staring at it. I prefer looking at galaxies. -- Sarah Hoyt
-
There is no overhead "inherit" in LINQ. There is some in the current JIT implementation of lambdas, but a better JITter could inline them, which would make them more efficient than functions.
Truth, James
-
There is a module for using actual, real SQL statements in code, rather than LINQ. I had to use it once for ad hoc sorting, because LINQ was way too cumbersome. Too bad the LINQ creators couldn't incorporate it.
Huh? I'm very confused by that statement. Are you attempting to sort a database table/query or an in-memory collection? Either way, I don't see how a proper SQL syntax would be any less "cumbersome" than the LINQ syntax.
Truth, James
-
Especially when combined with extension methods and fluent-style methods.
envvars
.Municipalities()
.Select(m => m.Fixups())
.NotServiceAccess()
.Where(m => m.VerifyConnection(_ => Log($"{m.Municipality}: {m.ConnectionString} => Connection failed.")))
.Do(munis =>
munis.SelectWith(m => M5.GetTableNames(AUDIT_SCHEMA, m.ConnectionString), (m, with) => (auditableEntities.NotIn(with, s => s.TableName.ToLower(), t => t.ToLower()), m))
.ForEach(q => q
.Iterate((t, m) =>
t
.Do(_ => Log($"{m.Municipality}: {t.TableName} => Audit table missing"))
.GenerateMissingAuditTableSql(m)
.Execute(m.ConnectionString, (sql, e) => Log($"{m.Municipality}: {t.TableName} => {e.Message}\r\nFailed to execute SQL: {sql.ToString()}"))
)))
.Do(munis =>
{
munis.SelectWith(m => M5.GetTableNames(AUDIT_SCHEMA, m.ConnectionString), (m, with) => (auditableEntities.In(with, s => s.TableName.ToLower(), t => t.ToLower()), m))
.ForEach(q => q
.Iterate((t, m) =>
{
Log($"{m.Municipality}: {t.TableName} => Checking...");
var entityColumns = M5.GetColumnList(DBO_SCHEMA, m.ConnectionString, t.TableName);
var auditColumns = M5.GetColumnList(AUDIT_SCHEMA, m.ConnectionString, t.TableName);entityColumns.NotIn(auditColumns, s => s.Name.ToLower(), f => f.Name.ToLower()) .DoIf(q2 => q2.Count() > 0, q3 => Log($" {q3.Count()} missing fields")) .ForEach(f => { Log($" {m.Municipality}: {t.TableName} => Field {f} missing in audit table"); f .GenerateMissingColumnSql(m, AUDIT\_SCHEMA, t.TableName) .Execute(m.ConnectionString, (sql, e) => Log($"{m.Municipality}: {t.TableName} => {e.Message}\\r\\nFailed to execute SQL: {sql.ToString()}")); }); })); });
This is a custom "one line" function that creates missing audit tables or adds the missing columns that the entity defines but someone forgot to add to the audit table. :-D
Latest Articles:
Client-Side Type-Based PublishThe more they complicate the plumbing, the easier it is to stop up the drain. One look at that, and I would start asking: 1. "What other ways can I do the same thing" 2. "Of those other ways, which provides the most value over the full SDLC?"
-
Especially when combined with extension methods and fluent-style methods.
envvars
.Municipalities()
.Select(m => m.Fixups())
.NotServiceAccess()
.Where(m => m.VerifyConnection(_ => Log($"{m.Municipality}: {m.ConnectionString} => Connection failed.")))
.Do(munis =>
munis.SelectWith(m => M5.GetTableNames(AUDIT_SCHEMA, m.ConnectionString), (m, with) => (auditableEntities.NotIn(with, s => s.TableName.ToLower(), t => t.ToLower()), m))
.ForEach(q => q
.Iterate((t, m) =>
t
.Do(_ => Log($"{m.Municipality}: {t.TableName} => Audit table missing"))
.GenerateMissingAuditTableSql(m)
.Execute(m.ConnectionString, (sql, e) => Log($"{m.Municipality}: {t.TableName} => {e.Message}\r\nFailed to execute SQL: {sql.ToString()}"))
)))
.Do(munis =>
{
munis.SelectWith(m => M5.GetTableNames(AUDIT_SCHEMA, m.ConnectionString), (m, with) => (auditableEntities.In(with, s => s.TableName.ToLower(), t => t.ToLower()), m))
.ForEach(q => q
.Iterate((t, m) =>
{
Log($"{m.Municipality}: {t.TableName} => Checking...");
var entityColumns = M5.GetColumnList(DBO_SCHEMA, m.ConnectionString, t.TableName);
var auditColumns = M5.GetColumnList(AUDIT_SCHEMA, m.ConnectionString, t.TableName);entityColumns.NotIn(auditColumns, s => s.Name.ToLower(), f => f.Name.ToLower()) .DoIf(q2 => q2.Count() > 0, q3 => Log($" {q3.Count()} missing fields")) .ForEach(f => { Log($" {m.Municipality}: {t.TableName} => Field {f} missing in audit table"); f .GenerateMissingColumnSql(m, AUDIT\_SCHEMA, t.TableName) .Execute(m.ConnectionString, (sql, e) => Log($"{m.Municipality}: {t.TableName} => {e.Message}\\r\\nFailed to execute SQL: {sql.ToString()}")); }); })); });
This is a custom "one line" function that creates missing audit tables or adds the missing columns that the entity defines but someone forgot to add to the audit table. :-D
Latest Articles:
Client-Side Type-Based Publish -
Especially when combined with extension methods and fluent-style methods.
envvars
.Municipalities()
.Select(m => m.Fixups())
.NotServiceAccess()
.Where(m => m.VerifyConnection(_ => Log($"{m.Municipality}: {m.ConnectionString} => Connection failed.")))
.Do(munis =>
munis.SelectWith(m => M5.GetTableNames(AUDIT_SCHEMA, m.ConnectionString), (m, with) => (auditableEntities.NotIn(with, s => s.TableName.ToLower(), t => t.ToLower()), m))
.ForEach(q => q
.Iterate((t, m) =>
t
.Do(_ => Log($"{m.Municipality}: {t.TableName} => Audit table missing"))
.GenerateMissingAuditTableSql(m)
.Execute(m.ConnectionString, (sql, e) => Log($"{m.Municipality}: {t.TableName} => {e.Message}\r\nFailed to execute SQL: {sql.ToString()}"))
)))
.Do(munis =>
{
munis.SelectWith(m => M5.GetTableNames(AUDIT_SCHEMA, m.ConnectionString), (m, with) => (auditableEntities.In(with, s => s.TableName.ToLower(), t => t.ToLower()), m))
.ForEach(q => q
.Iterate((t, m) =>
{
Log($"{m.Municipality}: {t.TableName} => Checking...");
var entityColumns = M5.GetColumnList(DBO_SCHEMA, m.ConnectionString, t.TableName);
var auditColumns = M5.GetColumnList(AUDIT_SCHEMA, m.ConnectionString, t.TableName);entityColumns.NotIn(auditColumns, s => s.Name.ToLower(), f => f.Name.ToLower()) .DoIf(q2 => q2.Count() > 0, q3 => Log($" {q3.Count()} missing fields")) .ForEach(f => { Log($" {m.Municipality}: {t.TableName} => Field {f} missing in audit table"); f .GenerateMissingColumnSql(m, AUDIT\_SCHEMA, t.TableName) .Execute(m.ConnectionString, (sql, e) => Log($"{m.Municipality}: {t.TableName} => {e.Message}\\r\\nFailed to execute SQL: {sql.ToString()}")); }); })); });
This is a custom "one line" function that creates missing audit tables or adds the missing columns that the entity defines but someone forgot to add to the audit table. :-D
Latest Articles:
Client-Side Type-Based PublishNice! However, I'm surprised you used old fashioned SQL to do the database update in light of what you are trying to illustrate.