Contribute to Open Source. Search issue labels to find the right project for you!

Limit API calls

privacyidea/privacyidea

certain (or all) token calls of the token-api could be limited. Like to allow users on set a pin or reset the failcounter only once an houer or two times per day.

See auth_max_success http://privacyidea.readthedocs.io/en/latest/policies/authorization.html#auth-max-success

We could add this as policy or we could enhance the basic policies to limit the application of the policy by number in time frame.

Updated 27/03/2017 11:24

Make creative mode per player

minetest/minetest

Continuation of here, as more people seem to think change is needed. I think the way creative mode is handled right now should be changed.

At the moment of writing, creative mode is a world option. This means that it’s either on or off, for everyone in the world. However, there are several use-cases to think off why one would want a single person to either enable or disable creative mode, and leave the rest of the players be.

Example: A popular survival server has griefer problems. To estimate the damages and try to rollback if needed, an admin would switch to creative, do his admin duty without having the risk to be killed by accidentally falling or annoying players trying to kill him, and revert back to survival once he is done.

I think a new option would have to be added when creating a world, to specify the default “gamemode”. No matter the gamemode of the players already in the world, any new players would get this gamemode on first join. Once in, they can change it (if they have the appropriate permissions obviously). This would also remove the need in singleplayer to leave the world only to turn on or off creative mode. Mods would need a way to check if a player is in creative mode or not of course.

Maybe handle more tasks for this on the mod side as well? Minetest could just tell mods if the player has the mode on or off, and mods could then decide what to do with that fact (negate damage, fly, etc).

I would like to hear your feedback.

Updated 27/03/2017 11:38

Photosphere support

SimpleMobileTools/Simple-Gallery

If the photo is detected to be a photosphere, it would be nice if it would be possible to open such file e.g. in Google Street View (or Google Photos), like what it’s done with videos…

Of course even nicer thing to do would be actually showing the pic as photosphere (parsing+rendering via OpenGL is actually not that hard… https://github.com/andree182/PythonPhotoSphere ).

Updated 27/03/2017 09:02

Rich Reporting

inasafe/inasafe

Problem

Currently, we already have rich attribute data from the analysis extent. However, this data is not presented yet in the analysis report. We can actually combine some of the attributes and get a new detailed information regarding the result. This new information hopefully can enrich our analysis report and give the user better understanding on what InaSAFE capable of doing.

This is some example that I extracted from the analysis result of Earthquake on population: image

Expected Behaviour

InaSAFE could show more information from the analysis details.

Proposed Solution

Add some new tables in the table report. :smile:

CC : @timlinux @Charlotte-Morgan @Gustry @ismailsunni @myarjunar @samnawi @felix-yew

Updated 27/03/2017 06:56

Display wordpress updates nicely in-game

uncovery/uncovery_me

We need to update the way wordpress updates (posts/comments) are displayed in-game. There need to be 2 buttons, one for the website link and one for the command in-game.

The title of the post should show properly. The code can be found here: https://github.com/uncovery/uncovery_me/blob/master/includes/wordpress_plugin.php#L190 and https://github.com/uncovery/uncovery_me/blob/master/includes/wordpress_plugin.php#L214

Updated 27/03/2017 05:25

ModifierVisitor combined with AstObserver

javaparser/javaparser

Greetings.

I am using an extended ModifierVisitor to change (add/change and remove code) an AST. I also wanted to use the AstObserver (with propagation) to monitor the changes I make to the AST.

My approach is to only override the ModifierVisitor methods that I’m interested in (eg. BlockStmt). However, the ModifierVisitor methods I don’t override reconstruct each Node to essentially create an identical Node. As an example here is a code snippet:

public Visitable visit(final BinaryExpr n, final A arg) { Expression left = (Expression) n.getLeft().accept(this, arg); Expression right = (Expression) n.getRight().accept(this, arg); Comment comment = n.getComment().map(s -> (Comment) s.accept(this, arg)).orElse(null); if (left == null) return right; if (right == null) return left; n.setLeft(left); n.setRight(right); n.setComment(comment); return n; }

The problem is this reconstruction triggers change events to the AstObserver even though no changes have actually occurred.

I’m just wondering if perhaps I’m misusing either ModifierVisitor/AstObserver or if anyone has recommendations on a better approach.

Thanks!

Updated 27/03/2017 12:06 4 Comments

Add a Twig extension to truncate titles on word boundaries

MarcusBarnes/mik

MIK’s InsertXmlFromTemplate metadata manipulator uses the Twig templating engine to generate MODS xml. Since titles longer than 255 characters are problematic in Islandora, one solution to populating MODS <title> elements with truncated text is to use a Twig template like this:

{% if Title|length < 256 %}
  <titleInfo>
     <title>{{ Title }}</title>
  </titleInfo>
{% else %}
  <titleInfo>
     {# Note that "slice" is not wordsafe. #}
     <title>{{ Title|slice(0, 250) }} [...]</title>
  </titleInfo>
{% endif %}

Problem is, Twig’s slice filter does not respect word boundaries.

I’d like to propose that we include a custom Twig filter as part of the InsertXmlFromTemplate metadata manipulator that will truncate strings on word boundaries. Adding a custom filter is documented at http://twig.sensiolabs.org/doc/2.x/advanced.html, and requires that the code for the filter be registered as part of the Twig environment, which in this manipulator is defined at https://github.com/MarcusBarnes/mik/blob/master/src/metadatamanipulators/InsertXmlFromTemplate.php#L54. We could probably use the “class method” implementation by defining the method within the InsertXmlFromTemplate class file itself, since that is where we need to register the custom filter.

SFU’s solution to the 255-char-max title issue may not be useful to other sites, but the custom Twig filter is not specific to that use case, it can be used to truncate any string at a word boundary.

Updated 26/03/2017 23:00

fully customizable z-lift issue/feature request

alexrj/Slic3r

Version

1.33.8 prusa edition, I know this is not the most relevant, but until the next release has gapfill fixed, there’s no way I’m going to use it.

Win 10 32/64

Behavior

I’ve turned on z-lift only above/below and it does not behave as I’d expect. The tooltip says this means the above value lets it skip the first above layer X and the below value limits it to below Y layers

And this is fine if you need that, but I would think people would want the opposite. I want hop ON for the first X layers to prevent peeling up a corner. And then OFF until above a certain height when it’s back ON to minimize deflecting of tall/thin parts

And it should just work with the appropriate values - when you make the “above” number higher than the “below” number, it should turn hop ON outside those values.

and file/stl, jst has to do with the hop only above/below

Updated 27/03/2017 12:32 9 Comments

Akka microserver for knowledge base queries

clulab/reach

We need a grounding microservice that minimally supports the following use cases:

  1. Endpoint receives a string, service returns all possible grounding IDs.
  2. Endpoint receives a grounding ID, service returns all possible synonyms.

Ideally, it would also have functionality to handle another use case:

  1. Endpoint receives a grounding ID, service returns the “short name”.
Updated 26/03/2017 18:08 4 Comments

It is really difficult to inspect mutations

vuejs/vue-devtools

When I’m inspecting a mutation I want to easily check the mutation data.

Right now, the mutation information is listed at the end of the inspect panel, the user needs to scroll all the way down(Through state & getters) to see it, this is an issue if your state and getters are big.

Solutions:

  • Move the mutation information to the top.
  • Create like tabs, or app bar with direct access buttons to the state, getters, a mutation information
  • Collapse state tree
Updated 26/03/2017 17:29

fastGet and fastPut with resumable/stoppable option

mscdex/ssh2

Hi, i’m using this library to transfer huge files. Now i have the problem of stopping and resuming a transfer, with fastGet and fastPut, it is not possible.

With simple createReadStream it is possible but the speed is way too slow. So, it would be awesome if some can make fastGet/fastPut resumable (continue transfer of a prev. started file) and also a possibility to stop the transfer.

Updated 26/03/2017 13:07

Input and Output files for a script build phase

workshop/struct

I’m wondering how can we specify extra parameters that Xcode allows to pass in every Script build phase (see screenshot attached).

<img width=“631” alt=“screen shot 2017-03-26 at 2 14 06 pm” src=“https://cloud.githubusercontent.com/assets/2624646/24331156/c3aa3dbc-122e-11e7-823b-c4bc5bd0d943.png”>

Updated 26/03/2017 15:49 2 Comments

FEATURE ENHANCEMENT | vbat min value alarm delay.

betaflight/betaflight

Hello, I am using the vbat alarm in addition to other telemetry option to monitor my vbat value. When i am doing vbat alert on the Taranis for example i add a 3-4 seconds delay so it will not alert me on every punch out i am doing.

I would think it can be very good option to add it to BF as well so we can add a delay to vbat min alert , where the default will be 0.

Updated 27/03/2017 04:30 2 Comments

Improve email address validation

BOINC/boinc

The current check of email addrs is syntactic; “1@1.1” passes. It’s easy for spammers or people suspended on the forums to create new accounts. Possible changes (non-exclusive): - Use a 3rd party validater like http://validateemailaddress.org/ (there are many; most of them charge) - Add a project option to require new accounts to be email-validated (the code for this already exists) and to hide unvalidated accounts.

Updated 26/03/2017 07:32

스팸 키워드 히트시 친절함에 대해서

rhymix/rhymix

2017-03-26 4 05 07 2017-03-26 4 01 47

스팸 키워드라고 스패머에게 알려주는 상황이 벌어져서 교묘하게 스팸에 등록한 키워드를 매일 매일 변경하여 스패머들이 등록 하는 것 같습니다. 예를 들면

꽁떡 -> 꽁'떡 -> 공떢 채팅앱->채'팅앱 -> 챗팅'앱

등등…

아무튼 얼럿은 가더라도 어떤 키워드가 스팸 키워드로 힛트 되었는지 알려주지 않아야 할거 같은데요.

Updated 27/03/2017 10:56 11 Comments

Introduce syntax for defining generic type argument constraints that would allow all implementations of a particular generic interface regardless to the interface type parameters used and enable the latter to be used in the resulting generic definition.

dotnet/csharplang

The task

Introduce syntax for defining generic type parameters constraints that would allow all implementations of a particular generic interface regardless to specific types used in the interface implementation (without the requirement for them to be specified) but make those available for referencing in the generic type definition (implicitly import type parameters of generic interfaces used as a new generic type parameters constraints into the generic type definition scope).

Example

What I mean is to make it possible to define, for example, a generic type ClassB<TA> that would let the TA type parameter to be assigned any type implementing a generic interface IInterfaceA<TB> in whatever a way [the interface definition allows], leaving the the actual type (being used as TA) to be specified at the instance definition place only, without including TB as a parameter in the signature of ClassB itself (what, I believe, means letting to avoid requiring unnecessary [for maintaining strong-typing non-ambiguity] limitations to be set and reducing definition redundancy) while, at the same time, keeping it possible to implement the resulting class logic still leveraging full awareness of what types are actually being used and being able to access (unless restricted another way) the members defined with these types freely.

E.g. something like the following (the example has been made as simplistic as it could be made to provide a self-explanatory C#-alike pseudo-code illustration for the very concept of the functionality being offered for consideration in the most pure manner possible and is not meant to demonstrate potential benefit from its possible usage in a practical use case nor to be comparable with currently available C# compiler implementations) but syntactically and semantically correct:

public interface IInterfaceA<TB> {

TB TheProperty {get; set;}

}

public class ClassB<TA> where TA : IInterfaceA<TB> {

TA TheProperty {get; set;}

TB ThePropertyProperty => TheProperty.TheProperty;

}

Given this example it can probably be worth emphasizing on that a particular type to be assigned to the TA parameter at the instance definition time can happen to be a non-generic class, a completely-defined implementation of IInterfaceA<TB> excepting no type arguments already, I believe this remark can explain why a less-verbose alternative to the ClassB<TA, TB> where TA : IInterfaceA<TB> syntax mentioned below can be useful at all.

Potential problems

As @vyrp has suggested at StackOverflow.com an ambiguity can take place if one class implements the same generic interface (the one we require) twice with different type parameters.

Existing alternative

As for now I am using an alternative definition similar to the following as a work-around to solve the same task I would like to use the above-described feature to:

public class ClassB<TA, TB> where TA : IInterfaceA<TB> {

TA TheProperty {get; set;}

TB ThePropertyProperty => TheProperty.TheProperty;

}

This gets the job done a way but I would like to humbly offer an idea of introducing what can be potentially considered a more elegant syntax for this semantics expression for the team consideration.

Updated 26/03/2017 22:34 1 Comments

Feature request: enable some way of handling external links by router.

vuejs/vue-router

I have read a number of discussions on this and think it’s worthwhile to raise this as an enhancement.

The following esults in each element rendering as an <li> with appropriate list styling but acting like a link. The problem is that if one of the links is to an external site it fails.

<template>
  <nav class="navs">
    <ul class="nav">
      <!-- -->
      <router-link
        class="nav__item nav__link"
        tag="li"
        active-class="-active"
        :to="nav.link"
        :key="nav.name"
        exact
        v-for="nav in navs">
        {{ nav.name }}
      </router-link>
    </ul>
  </nav>
</template>

It’s possible to convolute the logic with something like the following. It requires directly inserting the <a> elements but works given minor changes to CSS or always inserting links inside <li> elements (even though if there are no external links it can be coded using <router-link tag="li" ...>).

<ul>
  <li v-for="nav in navs">
    <a v-if="nav.external" class="nav__item nav__link" :href="nav.link">{{ nav.name }}</a>
    <router-link v-else
      class="nav__item nav__link"
      active-class="-active"
      :to="nav.link"
      :key="nav.name"
      exact
    >{{ nav.name }}</router-link>
  </li>
</ul>

I previously tried just inserting external URLs into the <router-link> elements and handling them in router.beforeEach(). It’s possible to apply some heuristic checks to see if the URL is external and set window.location.href if it is. But the problem I ran into then is that using the browser back button always resulted in an error because the history is stored as localhost:8080/http:/google.com (when testing with “http://google.com” as the external link).

It seems that that programmatically building lists of links is a common problem and that there should be a straightforward solution. Two solutions that would help me are 1) allowing the “external” prop on <router-link> elements that correctly stores history so the back button works or 2) provide some way in router.beforeEach() to prevent storing the unusable history entry. I think the first, or some variation where the externality of a link specified in the element, is the most straightforward.

I guess another solution is a strong recommendation in documentation on how to handle this seemingly common situation.

Thanks for considering it.

Updated 26/03/2017 12:23

Make SectionPolicy compataible with light DDD module struct

LaravelRUS/SleepingOwlAdmin

Имеем вот такую приблуду https://github.com/nWidart/laravel-modules

Этот пакет позволяет генерировать структуру для модуля совместимую с паблишингом своих пакетов сразу после написания логики. Так вот секции могут размещаться там - а механизма загрузки динамически расположенных политик секций мы не имеем.

Следовательно доработать.

Updated 26/03/2017 03:22

F# SDK needs to import design-time targets and authored into VS

dotnet/roslyn-project-system

The Microsoft.FSharp.DesignTime.targets needs to be imported just before importing Microsoft.Common.targets in these locations (that I know of):

  • FSharp.NET.SDK in the CLI repo - Sdk.OnRestore.targets
  • FSharp.NET.SDK NuGet package - FSharp.NET.Current.Sdk.targets
  • Microsoft.FSharp.targets under C:\Program Files (x86)\Microsoft SDKs\F#\4.1\Framework\v4.0, so that non-SDK projects know to import the design targets as well.

The code to import looks like this: xml <!-- Import design time targets for Roslyn Project System. These are only available if Visual Studio is installed. --> <!-- Import design time targets before the common targets, which import targets from Nuget. --> <PropertyGroup> <FSharpDesignTimeTargetsPath Condition="'$(FSharpDesignTimeTargetsPath)'==''">$(MSBuildExtensionsPath)\Microsoft\VisualStudio\Managed\Microsoft.FSharp.DesignTime.targets</FSharpDesignTimeTargetsPath> </PropertyGroup> <Import Project="$(FSharpDesignTimeTargetsPath)" Condition="'$(FSharpDesignTimeTargetsPath)' != '' and Exists('$(FSharpDesignTimeTargetsPath)')" />

The FSharp.NET.SDK from the CLI repo needs to be authored into VS as well. Ideally as part of this, the whole thing gets rationalized with the Microsoft.NET.Sdk.

Updated 26/03/2017 00:23 1 Comments

F# item templates don't show up

dotnet/roslyn-project-system

After creating a project, add item doesn’t show any templates even though the guid provider exists. I can’t even find the templates under common7\ide - so likely the regular logic doesn’t work and needs to be tweaked.

In the Resources property page, if I click on the link to create the resx file, it fails saying it cannot find the resx template for F#. This is likely related as well.

Updated 25/03/2017 23:59

F# property pages

dotnet/roslyn-project-system

All the property pages show up but fail with errors. This is because the property pages are reading some F# specific properties from the project file and we need to define XAML rules for those properties. The work here is to identify those properties and add the rules.

Updated 25/03/2017 23:59

F# language service integration

dotnet/roslyn-project-system

This is the known work:

  • [ ] The command line parser is stubbed out and needs to be implemented
  • [ ] There’s a hack for creating the WorkspaceContext. Roslyn needs to be changed to be able to create a context for F# as well.
  • [ ] To get the command line args, the F# SDK\Targets need to be updated to return the commandline args.
Updated 25/03/2017 23:59

Ability to choose columns by number or vector

fstpackage/fst

Hello.

read.fst is able to read columns indicating its name.

It would be great (and I think easy) to also be able to select the columns by its number position and more important with a vector of TRUES and FALSES.

It’s common to have that vectors when performing other operations, such as greps, or when reading from excel files with annotated information for every column.

Updated 26/03/2017 19:47 1 Comments

CODE FREEZE

HippieStation/HippieStation13

THIS IS A CODE FREEZE. PLEASE MAKE ALL NEW PRS TO THIS REPO: https://github.com/HippieStation/HippieStation

Updated 26/03/2017 23:14

Add Collabora Online support

servocoder/RichFilemanager

Collabora Online is an online document editing and sharing system, similar to Google Docs. It is based on LibreOffice, and has an Open Source license. It is self-hosted (currently it is distributed as a Docker image).

Pydio, which is a web-based file manager similar to RFM, has already added support for Collabora Online. A video of it can be seen here:

https://www.youtube.com/watch?v=OjHtgnL_L7Y

As a wishlist item, it would be nice if RFM could support this too, using a plugin.

Note that Collabora Online is a very large (hundreds of megs) server-side deployment, so it would be a separate download and install. Also, I think it needs a concept of “Users” with it, which RFM does not have built-in.

I will read up on the Collabora Online API and see if this is a plausible feature for RFM.

Updated 25/03/2017 18:18 1 Comments

能否支持下载百度网盘的视频

soimort/you-get

百度网盘里存了很多电影,在线可以播放,但是我习惯多倍速播放,想下载下来,但是网盘下载速度很慢,刚才试了下,但是不能,不知道能不能实现 you-get –debug https://pan.baidu.com/play/video#video/path=%2FBT%2FGame.of.Thrones.S01.2011.BluRay.720p.x264.DTS-CnSCG%2FGame.Of.Thrones.S01.E02.2011.BluRay.720p.x264.DTS-CnSCG.mkv&t=-1 [1] 70910 omaidbdeMacBook-Air:~ omaidb$ Generating cookies… [DEBUG] get_content: http://pan.baidu.com/play/video#video/path=%2FBT%2FGame.of.Thrones.S01.2011.BluRay.720p.x264.DTS-CnSCG%2FGame.Of.Thrones.S01.E02.2011.BluRay.720p.x264.DTS-CnSCG.mkv you-get: version 0.4.652, a tiny downloader that scrapes the web. you-get: [‘https://pan.baidu.com/play/video#video/path=%2FBT%2FGame.of.Thrones.S01.2011.BluRay.720p.x264.DTS-CnSCG%2FGame.Of.Thrones.S01.E02.2011.BluRay.720p.x264.DTS-CnSCG.mkv’] Traceback (most recent call last): File “/usr/local/bin/you-get”, line 11, in <module> load_entry_point(‘you-get==0.4.652’, ‘console_scripts’, ‘you-get’)() File “/usr/local/Cellar/you-get/0.4.652/libexec/lib/python3.6/site-packages/you_get/main.py”, line 92, in main main(kwargs) File “/usr/local/Cellar/you-get/0.4.652/libexec/lib/python3.6/site-packages/you_get/common.py”, line 1407, in main script_main(‘you-get’, any_download, any_download_playlist, kwargs) File “/usr/local/Cellar/you-get/0.4.652/libexec/lib/python3.6/site-packages/you_get/common.py”, line 1320, in script_main download_main(download, download_playlist, args, playlist, output_dir=output_dir, merge=merge, info_only=info_only, json_output=json_output, caption=caption) File “/usr/local/Cellar/you-get/0.4.652/libexec/lib/python3.6/site-packages/you_get/common.py”, line 1136, in download_main download(url, kwargs) File “/usr/local/Cellar/you-get/0.4.652/libexec/lib/python3.6/site-packages/you_get/common.py”, line 1400, in any_download m.download(url, kwargs) File “/usr/local/Cellar/you-get/0.4.652/libexec/lib/python3.6/site-packages/you_get/extractors/baidu.py”, line 108, in baidu_download real_url, title, ext, size = baidu_pan_download(url) File “/usr/local/Cellar/you-get/0.4.652/libexec/lib/python3.6/site-packages/you_get/extractors/baidu.py”, line 183, in baidu_pan_download raise AssertionError(“Share not found or canceled: %s” % url) AssertionError: Share not found or canceled: http://pan.baidu.com/play/video#video/path=%2FBT%2FGame.of.Thrones.S01.2011.BluRay.720p.x264.DTS-CnSCG%2FGame.Of.Thrones.S01.E02.2011.BluRay.720p.x264.DTS-CnSCG.mkv

Updated 25/03/2017 18:10 4 Comments

browse: implement OPTIONS and PROPFIND

mholt/caddy

I’d like to extend the built-in plugin browse by HTTP methods OPTIONS and (trivial) PROPFIND. Both are read-only. PROPFIND will add a third view to browse, which currently renders for text/html and application/json. Would you entertain a corresponding PR?

The changes will enable users of some Windows versions to enter the URL of an endpoint (representing a directory; browse displays directories) in Windows Explorer and see its contents as if it were a local folder.

Updated 26/03/2017 19:02 4 Comments

Discussion : Omitting new keyword

dotnet/csharplang

There are lot situations where new keyword can be omitted.

var p = new Point();

can be

var p = Point();

Keyword new will be required to resolve ambiguity, for example if Point() function and Point class are defined and for other such cases. Benefit is saved space, particularly with calling function and passing many new objects as arguments.

Updated 26/03/2017 22:33 8 Comments

Trigger Alert for IP Reassignment

ntop/ntopng

Implement a ARP-based mechanism (similar to https://en.wikipedia.org/wiki/Arpwatch) for detecting changes in IP/MAC association.

As the latter case can also be triggered by overlapping IPs we need to pay attention to ARP messages to detect these situations, and eventually trigger a (user-configurable) alert.

Updated 25/03/2017 10:21

(Proposal) Extension properties and indexers

dotnet/csharplang

Normally, IsXyz should be a boolean property. As “extension properties” are not allowed this is implemented as extension methods, what breaks the appearance a bit.

I propose to introduce extension properties: ```C# // code originally from Roslyn/TypeSymbolExtensions.cs // currently implemented as methods public static bool IsIntrinsicType[this TypeSymbol type] { get => type.SpecialType.IsIntrinsicType; }

    public static bool IsPartial[this TypeSymbol type]
    {
        get
        {
            var nt = type as SourceNamedTypeSymbol;
            return (object)nt != null && nt.IsPartial;
        }
    }

    public static bool IsPointerType[this TypeSymbol type]
    {
        get => type is PointerTypeSymbol;
    }
The method characterising parantheses are just replaced by brackets.
I think it will not break the overall appearance of properties and indexers, because for indexers the index is also passed as parameter within brackets, and it will also allow for extension indexers

public int this[this ExtendedType type, int index] { get => {NOP}; set => {NOP}; } ```

Updated 26/03/2017 22:34 1 Comments

MAKE MAPP GO ZOOM ZOOM

RocketMap/RocketMap

Description

MAPP SHOULD GO ZOOM ZOOM! I REMOVE STUFF THAT MAKE MAP GO slow slow

Motivation and Context

MAP DOES NOT EVEN GO ONE ZOOM

How Has This Been Tested?

NO MORE WEIGHT, MAP CAN ZOOM ZOOM

Screenshots (if appropriate):

Types of changes

smol change - [X] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • [X] My code follows the code style of this project.
  • [ ] My change requires a change to the documentation.
  • [ ] I have updated the documentation accordingly.
Updated 26/03/2017 23:43 6 Comments

Implement ICMP and ARP Distribution

ntop/ntopng

Similar to /lua/if_stats.lua?page=packets it is request to add new pie charts (both for local hosts and interfaces) where are depicted (see #1085) - ARP request vs response - ICMP flags distribution (echo, dest unreachable …)

Both distribution should be divided in sent vs received. Example - account the number of ICMP ECHO request sent and rcvd

Both directions (sent and rcvd) must be depicted.

Updated 25/03/2017 08:25

Implement TCP/ARP/ICMP packets ratio and alerts

ntop/ntopng

For every host(mac) compute the - ARP request/response ratio - ICMP ECHO request/response ratio - TCP SYN/SYN_ACK ratio

Generate (local) host alerts when those ratio significantly divert from 1:1. For alert generation please extend the host alert min/5min/hour/daily mechanisms already present (/lua/host_details.lua?page=alerts&tab=alert_settings)

Updated 25/03/2017 08:27

Unhide subs if loaded track is forced

mpv-player/mpv

If the sub track loaded by default by the player has the Forced flag enabled then if the user also has –no-sub-visibility set in their config that option should be reversed to –sub-visibility as the Forced flag is usually used for sub tracks with “non english parts” only. If the user has subs hidden by default they may not be aware this track even exists and miss out on dialog that the director intended to be seen in foreign speaking parts.

I say ‘loaded by default’ because if your –slang preference is to another language that’s available it will still be loaded by default, ignoring the fact there’s a track asking to be Forced. Unless that language also has a track with a Forced flag, then it’ll use that obviously. (EDIT: I’m not saying change this, this is good, just the thread title).

EDIT: It’s said better than I have here, http://kodi.wiki/view/subtitles#Using_Forced_Subtitles Basically I’m asking if mpv could do like Kodi does for Forced subs.

I guess the title I should have used was “Make mpv handle Forced subs in the same way Kodi does”.

Updated 26/03/2017 09:40

cli argument to prevent snapshot recording during CI

facebook/jest

Do you want to request a feature or report a bug?

feature

What is the current behavior?

I can’t ensure that all snapshots were recorded before running test in CI. Unrecorded snapshots will be written on the CI server fs and the test suite will pass.

What is the expected behavior?

I can ensure that the test will fail if it tries to create a new snapshot.

--recordSnapshot    Records snapshots.
                    Useful to disable when you want
                    to make sure all snapshot are already recoded (e.g: on CI)
                    Disable using --no-recordSnapshot.
                    [boolean] [default: true]
Updated 26/03/2017 00:53 2 Comments

Add support to use __constant's in native CUDA kernels

libocca/occa

Try out the following to see if we can add __constant to work on native CUDA kernels. Manually put the constant variable/array with a name in the kernel file

__constant float myVar;
__constant float myArray[10];

Compile kernel

occa::kernel foo = device.buildKernel('foo.cu', 'foo')

Use an OCCA helper method to initialize the constant​ value. The ‘extra work’ part is keeping track of the variable name and size outside of the kernel:

float myVar = 10;
float *myArray = new float[10];
​// Initialize myArray​

occa::cuda::initConstantMemory(foo, 'myVar'  , &myVar , sizeof(float));
occa::cuda::initConstantMemory(foo, 'myArray', myArray, 10 * sizeof(float));
Updated 25/03/2017 21:51 1 Comments

Context -bound nameof() operator

dotnet/csharplang

@comdiv commented on Wed Nov 25 2015

For now:

// it's legal code
public const string S = nameof(S); 


public void Method() {
   //this is not
     var _s = nameof(_s);
}

In second case it fail with “Cannot use local variable ‘_s’ before it is declared ”.

I understand that problem is scope and renaming - right side knows outer scope.

My suggestion - add context-bound nameof() operator - for example nameof(var), nameof(void) and nameof(class). Checked - for now all this forms are compile error - so they can be used.

namespace A{
class X {
    protected string fieldname = nameof(var); // should be "fieldname "
    protected string declname = nameof(class); //sould be "A.X"
    protected string tname = nameof(this); // "A.X" here
    protected string bname = nameof(base); // "System.Object" here
    virtual void Print () {
        var _x = nameof(var); // should be "_x"
        var y = nameof(void); // should be Print
        Console.WriteLine( $"{fieldname} {declname} {tname} {bname} {_x} {y}");
    }
}
class Z : X {}
}
...
new X().Print();
// cout:   fieldname A.X A.X System.Object _x Print
new Z().Print();
// cout:  fieldname A.X Z.X A.X _x Print

from my point of view:

keywords and it's implementation

nameof(class) - always name of DECLARATION class 
     inplace substitute with string literal

nameof(this) - name of current object instance class 
    if in static context - same as nameof(class), if not - 
    add `private static @____this_name =    nameof(class)` 
    in all classes where 1) nameof(this) is in compile body 2) if base class has such 
    field (mean that it's possible that nameof(this) is in ancestor's methods)
    and then replace `nameof(this)` with `@____this_name`

nameof(base) - name of base class of current - 
    same as `nameof(this)` but with referencing parent class 


nameof(void) - name of closest Method in scope - 
    simply lookup closest Method declaration. So it will be work in lambda too:
        public void X() {
            var t = new {1,2,3}.Select(i=>nameof(void)+i);// it's still X1, X2, X3
        }
alternate to nameof(void) can be nameof() - with empty braces
But if it's in property it should reference Property name:
    public string X {
        get { return nameof(void);} // "X"
    }
    so nameof() is looks like better syntax than nameof(void)


nameof(var) - name of left side in initializers (variables,fields, properties)
        lookup for closest initialize variable operator and take it's name part
    if it's not variable initializer - it lookup for Property or Field initializer and get name from it

Profit: It’s better for refactoring without tools - we not require replacing in several places. It’s allow to reference left side variable It’s good for logs, exception formating - code became more readable and avoid usual copy-paste errors that are common for such code parts:

void Op1(){
    log.Debug($"start {nameof(Op1)}");
    ....
    log.Debug($"finish {nameof(Op1)}");
}
void Op2(){
    log.Debug($"start {nameof(Op2)}");
    ...
    log.Debug($"finish {nameof(Op1)}"); //uuupss
}

but if nameof(void) will be added:
void Op1(){
    log.Debug($"start {nameof(void)}");
    ....
    log.Debug($"finish {nameof(void)}");
}
void Op2(){
    log.Debug($"start {nameof(void)}");
    ...
    log.Debug($"finish {nameof(void)}");
}

It’s good for code generation - we not require control all names if just require generate some logging / serialization logic It’s good in custom serialize-deserialize while nameof(var) can be used

It’s not breaking change.


@alrz commented on Wed Nov 25 2015

C# Design Meeting Notes for Mar 4, 2015

This works the same as with any other construct, i.e.: not. This is not a special case for nameof, and it doesn’t seem worth special casing to allow it.

766


@comdiv commented on Wed Nov 25 2015

nameof is operator to kill doubling, ambiguity and magic-strings - think it should be extended


@m0sa commented on Thu Feb 04 2016

+1 would love to see this


@jrmoreno1 commented on Mon Feb 08 2016

I found this by looking to see if someone had already reported a need for nameof(void) – I have several projects where that would make adding properties much easier; the property references a resource that is supposed to have the same name (config file or resources), I could then use the same code for all of them, just changing the property name and it would work. While nameof(property) is better than “property”, it is still a bit fragile because of copy/paste/edit (or rather not editing).


@comdiv commented on Wed Feb 10 2016

+1 resource idea is very good, I think - it can be even with localization support.


@jrmoreno1 commented on Wed Jul 20 2016

An additional usage that might be beneficial (encountered just today) is referencing a parent class or namespace – but I can’t think of a good syntax for it.

Update: on thinking about it, a good syntax might be Console.WriteLine(NameOf(void, Namespace); Console.WriteLine(NameOf(void, Class); Console.WriteLine(NameOf(void, Method); Console.WriteLine(NameOf(void, Property); Console.WriteLine(NameOf(void, Parent); // For nested class Console.WriteLine(NameOf(void, Base); // For class that this class inherits from

Possibly even Console.WriteLine(NameOf(void, Type);

Updated 26/03/2017 04:22 1 Comments

Proposal: Implicit Interfaces

dotnet/csharplang

@gregsdennis commented on Tue Apr 21 2015

<div> <div>

<h3>The Problem</h3> Define an interface in such a way that its entire purpose is to represent a set of other interfaces.

Suppose you have two interfaces: <pre><code>interface IA { void SomeMethod(); }

interface IB { void SomeOtherMethod(); } </code></pre> Now suppose you want to create a property on an object into which you can place an object of either type. Since they have no common ancestry, you would have three options (that I’ve seen, you may devise your own):

<ul> <li>declare the property as <code>object</code> and then test/cast in order to access the functionality <pre><code>class MyImpl : IA, IB { public void SomeMethod() { … } public void SomeOtherMethod() { … } }

class MyClass { public object MyProp { get; set; } }

class MyApp { static void Main(string[] args) { var myClass = new MyClass { MyProp = new MyImpl() }; ((IA)myClass.MyProp).SomeMethod(); ((IB)myClass.MyProp).SomeOtherMethod(); } } </code></pre> </li> <li>create a third interface defined as the combination of the two <pre><code>interface ICombined : IA, IB {}

class MyImpl : ICombined { public void SomeMethod() { … } public void SomeOtherMethod() { … } }

class MyClass { public ICombined MyProp { get; set; } }

class MyApp { static void Main(string[] args) { var myClass = new MyClass { MyProp = new MyImpl() }; myClass.MyProp.SomeMethod(); myClass.MyProp.SomeOtherMethod(); } } </code></pre> </li> <li>create a proxy type which exposes a single field via independent properties <pre><code>class MyProxy<T, TA, TB> where T : TA, TB { private object _value;

public TA AsA { get { return (TA)_value; } }
public TB AsB { get { return (TB)_value; } }

public MyProxy(T value) { _value = value; }

}

class MyClass { public MyProxy MyProp { get; set; } }

class MyImpl : IA, IB { public void SomeMethod() { … } public void SomeOtherMethod() { … } }

class MyApp { static void Main(string[] args) { var myClass = new MyClass { MyProp = new MyProxy<MyImpl, IA, IB>(new MyImpl()) }; myClass.MyProp.AsIA.SomeMethod(); myClass.MyProp.AsIB.SomeOtherMethod(); } } </code></pre> </li> </ul> The second option is generally the more preferred option, however, it’s not always doable. What if, instead of <code>IA</code> and <code>IB</code>, we use <code>IComparable</code>and <code>IConvertible</code>? <pre><code>interface ICombined : IComparable, IConvertible {}

class MyImpl : ICombined { // IComparable implementation public int CompareTo(object obj) { … }

// IConvertible implementation
public int ToInt32() { ... }
...

}

class MyClass { public ICombined MyProp { get; set; } }

class MyApp { static void Main(string[] args) { var myClass = new MyClass { MyProp = new MyImpl() }; var comparison = myClass.MyProp.CompareTo(new object()); var newInt = myClass.MyProp.ToInt32(); } } </code></pre> This only works for classes which specifically implement the <code>ICombined</code> interface. You would not be able to assign types like <code>int</code>, <code>double</code>, and<code>string</code>, each of which implement both <code>IComparable</code> and <code>IConvertible</code>. <h3>The Solution</h3> We introduce a new usage of the <code>implicit</code> keyword for interfaces. <pre><code>implicit interface ICombined : IComparable, IConvertible {} </code></pre> This tells both the compiler and the run-time that any class which implements both <code>IComparable</code> and <code>IConvertible</code> can be interpreted as implementing <code>ICombined</code>.

The remainder of the code could stay the same, but now, in addition to explicit implementations of <code>ICombined</code> we could also assign any type which implements both <code>IComparable</code> and <code>IConvertible</code>, including <code>int</code>, <code>double</code>, and <code>string</code>. <pre><code>class MyApp { static void Main(string[] args) { var myClass = new MyClass { MyProp = 6 }; var comparison = myClass.MyProp.CompareTo(new object()); var newInt = myClass.MyProp.ToInt32();

    myClass.MyProp = "example";
    var newComparison = myClass.MyProp.CompareTo(new object());
    ...
}

} </code></pre> Additionally, you could use this new interface to define a collection of such objects: <pre><code>var list = new List<ICombined> { 6, “string” }; </code></pre> Defining an interface this way, it becomes retroactive. That is, types which implement all base interfaces for the implicit interface also are said to implement the implicit one. <h3>The Rules</h3> <ol> <li>An implicit interface may combine any number of interfaces.</li> <li>An implicit interface may not define any additional functionality. That is, it must be empty.</li> </ol> That’s really it.

Finally, the run-time will have to do some type checking, which it should do already for the <code>is</code> and <code>as</code> keywords. It wouldn’t need to know <em>all</em> implicit interfaces that a type implements, it would just need to check as requested. <pre><code>var implemented = 6 is ICombined; </code></pre> This basically asks, “Does the type of <code>6</code>, which is <code>int</code>, implement <code>ICombined</code>?” To determine that, it sees that <code>ICombined</code> is an implicit interface so it asks, “Does it implement all of the interfaces implmented by <code>ICombined</code>?” So it’s equivalent to writing: <pre><code>var implemented = 6 is IConvertible && 6 is IComparable; </code></pre> Simple field and property assignments would be compiler-verifiable. </div>

<h2></h2>

</div>


@HaloFour commented on Tue Apr 21 2015

The compiler might be able to sneakily handle that within the code that it compiled itself but it couldn’t affect how other assemblies might treat that type. To make the CLR recognize int as an ICombined would require changes to the runtime.

You might want to submit this as a feature request to the CoreCLR team.


@dsaf commented on Wed Apr 22 2015

Is it related to intersection types?


@gregsdennis commented on Wed Apr 22 2015

@dsaf, not really, but I can see the proximity to that idea.

The concept behind this is closer to type verification by implementation. I remember reading about a feature that some languages have where the class is defined not by some concrete Type concept, but rather by the functionality that the class provides. By this, a class can be considered to implement an interface simply by implementing the contract it states (whereas C# requires you to explicitly state you’re implementing the interface, even if the contract happens to match some other interface).

This could considered be a partial implementation of that feature, but still keeping to the ideals which already exist in C#.


@gregsdennis commented on Wed Apr 22 2015

@HaloFour, I was going to say that the CLR wouldn’t have to change, citing that

var implemented = 6 is ICombined;

could be converted by the compiler into

var implemented = 6 is IConvertible && 6 is IComparable;

before translating to IL.

However, now that I think about it further, it would still need to have a type for any variable which holds an ICombined value. Otherwise, it would have to use object and inject a lot of casts to switch between the various interfaces when it needs to process the value. That could lead to other issues.

Regarding use in other assemblies, those assemblies would have to reference this one to get the type definition of ICombined. How would this be a problem for those assemblies?


@HaloFour commented on Wed Apr 22 2015

You could handle this via a helper method that does some reflection (obviously caching the results). I actually had some incubator project some years back to provide a duck-typing helper method that would construct a concrete proxy class in a dynamic assembly that would implement the interface members and point them to compatible members of the target type. It worked nice but it had the same issues where the proxy type isn’t the same as the target type and you can’t convert between them. The compiler would have the same issue. If it emitted a synthetic type the instance is no longer the original type. You couldn’t pass that ICombined to another method and cast it to an int.


@bondsbw commented on Wed Apr 22 2015

@gregsdennis

An implicit interface may not define any additional functionality. That is, it must be empty.

In that case it might make more sense to remove the braces:

implicit interface ICombined : IComparable, IConvertible;

@gafter commented on Fri Nov 20 2015

I wonder if intersection types would be a better fit, since there is little reason to give a name to the combination.


@benaadams commented on Sat Nov 28 2015

Have lots of these types in https://github.com/dotnet/coreclr/issues/2179 that require naming for ease of use.


@Thaina commented on Wed Mar 09 2016

I would prefer that we could alias and cast or check for a group of type than making new implicit interface

For solving your problem it would better if we just

using ICombined = (IConvertible,IComparable); 
if(obj is (IConvertible,IComparable))
   return obj as (IConvertible,IComparable);
var list = new List<(IConvertible,IComparable)>();

Syntax is (type,type) or maybe (type & type) and (type | type)

But it would require CLR support


@gregsdennis commented on Wed Mar 09 2016

@Thaina, I think your idea is good. I like the idea of declaring the shorthand in the using statement.

I think the (type | type) syntax would explain the concept better in code. It is literally “this or that type.”


@HaloFour commented on Wed Mar 09 2016

The (A, B) syntax is proposed for tuples. I like (A & B) since the intersected type would have to implement both interfaces. The concept of (A | B) is interesting, a type that implements either interface and the consumer can only access shared members. Java does have limited typing like this in exception handlers, e.g. catch (IOException | SQLException exception) { }.

I wonder how much of either concept that the compiler could implement without CLRsupport. There are tricks that the compiler could do within a method, but it would have to be pretty limited.


@gregsdennis commented on Wed Mar 09 2016

@HaloFour, you are correct: the desired syntax for this should be (A & B). (Early morning; brain not booted.)


@aluanhaddad commented on Thu May 12 2016

Intersection types would add a great deal of expressiveness to the language. I really want to see this implemented and I’m really happy to see renewed interest. This would allow for much more powerful and expressive consumption of generic APIs and allow for powerful, typesafe ad hoc cross axial classification of types. I think the & syntax is a good choice and has worked out very well in languages like TypeScript.

As for the question of declaring a name for some intersection type, I think the using syntax would provide that intuitively.


@Thaina commented on Sun Jun 05 2016

I have seen many proposal about intersect/union type at where clause. And I think it all could be relate to trait too

Should we have some thread or tag to sum up all these kind of proposal as generic enhancement or type constraint ?


@aluanhaddad commented on Fri Jun 24 2016

@Thaina the problem is that while

where T: IComparable, IEquatable

works very well already for specifying intersecting type constraints, it is impossible to call such a method (with resorting to dynamic) without casting to a type implementing both interfaces. Such a definition may not be available, and if it is it is still not ideal. I would welcome a thread gathering ideas for these proposals, but it is about much more than specifying generic constraints. Basically, Union Types would be very useful in generic constraints. Intersection types would be very useful for consuming generic methods and for pattern matching.

Updated 25/03/2017 01:26 3 Comments

Proposal: Allow Lambda as Argument to an Attribute

dotnet/csharplang

@sirisian commented on Sat May 02 2015

Essentially allow lambdas as arguments to attribute constructors.

Code example. Specifically the “[Converter(s => s == "one” ? 1 : 0)]“ line and "public ConverterAttribute(Func<string, int> converter)” in the constructor.

Possible use cases I’ve seen from years ago are converters for serialization libraries and alternative ways to define validator functions.

using System;
using System.Linq;

namespace AttributeTest
{
    [AttributeUsage(AttributeTargets.Property)]
    public class ConverterAttribute : System.Attribute
    {
        public Func<string, int> Convert
        {
            get;
        }
        public ConverterAttribute(Func<string, int> converter)
        {
            this.Convert = converter;
        }
    }

    class BaseItem
    {
        public int GetTotal()
        {
            return this.GetType().GetProperties().Select(propertyInfo => ((ConverterAttribute)propertyInfo.GetCustomAttributes(typeof(ConverterAttribute), true).First()).Convert((string)propertyInfo.GetValue(this))).Aggregate(0, (input, value) => value + input);
        }
    }

    class DerivedItem : BaseItem
    {
        [Converter(s => s == "one" ? 1 : 0)]
        public string Foo
        {
            get;
            set;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var convertedItem = new DerivedItem();
            convertedItem.Foo = "one";
            Console.WriteLine(convertedItem.GetTotal());
        }
    }
}

@HaloFour commented on Sat May 02 2015

C# is limited by the CLR in the types of the parameters that can be used for custom attributes. Those values need to be easily and predictably serialized/deserialized as they are embedded as a BLOB directly in the assembly metadata and reconstructed by the run time. The compiler could probably emit anything it wanted in the BLOB but the CLR itself can only understand and deserialize the integral types, bool, char, string, Type (serialized as a string of the type name) and arrays of those types.

Given that, how would a lambda be embedded? They can’t really be serialized, even if the limitation on the CLR could be lifted. Only thing I could think of is that the compiler generates a synthetic public type with a public static method and then serializes the method runtime handle. The attribute itself would have to be defined in a way that the property is really of long so that the CLR would deserialize the value of the method handle which would be converted to a RuntimeMethodHandle and MethodBase.GetMethodFromHandle called to obtain the MethodBase which is then converted into a delegate, but how to make that seamless sounds messy.


@MaulingMonkey commented on Wed Mar 15 2017

“Only thing I could think of is that the compiler generates a synthetic public type with a public static method”

This is basically how lambdas already work. For:

using System;
using System.Collections.Generic;
using System.Reflection;

static class Program
{
    public static void Main(string[] args)
    {
        var l = new List<int>() { 1, 2, 3 };
        l.RemoveAll(i => i%2 == 0);
        foreach (var i in l) Console.WriteLine(i);
    }
}

Roughly the following is generated: ```cs private class <>c { public <>c() {} internal bool <Main>b__0_0(int i) { return i%2 == 0; }

public static <>c <>9 = new c<>();
public static Predicate<int> <>9__0_0 = new Predicate<int>(<>9.<Main>b__0_0);

} ```

Multiple lambdas may be collapsed into a single class (depending on if they share the same captured state? - none in this case…)

System.Runtime.Serialization.Formatters.Binary.BinaryFormatter can currently (de)serialize delegates - presumably by persisting the object instance and method name or similar, although this is potentially rather brittle. A less general purpose method that might work here (by virtue of being unable to capture local method state when constructing attributes, and thus always being able to generate a static delegate instance to reference) would be to simply persist the name of the static field (“<>c.<>9__0_0”).

Updated 25/03/2017 00:11

Asset acceptance email with bulk import

snipe/snipe-it

Expected Behavior (or desired behavior if a feature request)

on bulk import assets from CSV, also send asset acceptance emails


Actual Behavior

(what actually happens goes here)


Please confirm you have done the following before posting your bug report:


Please provide answers to these questions before posting your bug report:

  • Version of Snipe-IT you’re running
  • What OS and web server you’re running Snipe-IT on
  • What method you used to install Snipe-IT (install.sh, manual installation, docker, etc)
  • WITH DEBUG TURNED ON, if you’re getting an error in your browser, include that error
  • What specific Snipe-IT page you’re on, and what specific element you’re interacting with to trigger the error
  • If a stacktrace is provided in the error, include that too.
  • Any errors that appear in your browser’s error console.
  • Confirm whether the error is reproduceable on the demo.
  • Include any additional information you can find in app/storage/logs and your webserver’s logs.
  • Include what you’ve done so far in the installation, and if you got any error messages along the way.
  • Indicate whether or not you’ve manually edited any data directly in the database
Updated 24/03/2017 21:55

Feature request: Better way of treating null as empty enumerable in foreach loops

dotnet/csharplang

@rickardp commented on Wed Nov 04 2015

Consider the following loop:

IEnumerable<SomeType> myEnumerable = ...

foreach(var item in myEnumerable ?? Enumerable.Empty<SomeType>) {
    ...
}

which will default to an empty enumerable in case myEnumerable above is null. This becomes quite awkward when SomeType is a rather complex type (Like Dictionary<string, Func<Tuple<string, int>>>), or even impossible if the type is anonymous.

One way this can be solved right now is to create an extension method, e.g.

public static IEnumerable<T> EmptyIfNull(this IEnumerable<T> enumerable) {
   return enumerable ?? Enumerable.Empty<T>();
}

which is not bad at all actually (though still not built into LINQ AFAIK), but I think that it would be better still if there was a way similar to the null-propagation operators (?. and ?[), e.g. (hopefully with a better syntax)

foreach?(var item in myEnumerable) 
    ...
}

I understand that constructing the syntax for a solution to this problem can be tricky, but I think it is at least worth considering since I believe the case is quite common (I find it a lot more common than the null-propagation indexer operator in my code).

Why using null at all and not empty enumerables everywhere? One example where I find the scenario common is in serialization of objects, where empty collections are omitted and should therefore semantically be identical to null. Since default(IEnumerable<>) is null, this means that null will be returned when the key is not found. This would also add symmetry with null propagating index operators.


@dsaf commented on Thu Nov 05 2015

The question mark should probably be next to enumerable rather than the keyword? Although there might be some ambiguity I guess…

foreach (var item in myEnumerable?)
{
}

@vladd commented on Fri Nov 06 2015

Well, in my opinion the empty enumerable should be distinguishable from null enumerable object, so the two should not behave in the same way. In particular, the whole LINQ world (.Select. .Where, .Concat etc.) throws on null, but works correctly with empty sequence. Making enumerating null a special case would create inconsistency between the language and the standard library.

(If you encounter often nulls returned from some API, meaning empty sequences, maybe it’s API what should be corrected?)


@rickardp commented on Sat Nov 07 2015

@vladd I think your point is very valid, and in this way C# differs from, for example, Objective-C where a nil array is essentially the same as an empty array.

The reason that I think this would be helpful is not helping to deal with broken APIs but rather interaction with dynamic languages and objects, generics where default(T) is returned e.g. when a key is not found. To give a concrete example, consider some JSON parser generated from C# classes, parsing configuration data.

public class Configuration 
{
    public List<string> LogFiles { get; set; }
}

Then, to handle the case where the user might have omitted the LogFiles key entirely, or provided an empty array, you are doing something like this:

if (config.LogFiles != null)
{
    foreach (var logFile in config.LogFiles)
    {
        ....
    }
}

I tend to see this pattern a lot (in my code and others') especially when it comes to dealing with data serialization and interaction with external programs.

For LINQ and index operators we already have null propagation that helps with null checking. I think it is still worth considering some kind of symmetry with foreach since that is such a useful construct.


@bbarry commented on Sat Nov 07 2015

I don’t know if it is particularly useful but you can always do:

myEnumerable?.ToList().ForEach(item => ...); // .ToList() may be unnecessary

or:

myEnumerable?.AsParallel().ForAll(item => ...);

@aluanhaddad commented on Fri Nov 13 2015

@rickardp This is interesting. Most of the time, returning null for collection types likely indicates a badly designed API. The serialization point however, is worth examining in more detail. I also run into this issue/question regularly. I think the correct way to handle it is often to customize the serialization/deserialization to impose the semantics you desire. If you are writing the serialized classes, you can initialize collection properties to empty.

That said, the question of whether empty and null enumerables should be treated as semantically equivalent is just as relevant in the context of serialization as it is in any other. That an object has been serialized does not imply that these semantics should change. For example, as someone who does both frontend and backend development on a daily basis, I would rather receive an empty array than nothing when I am deserializing JSON in JavaScript.


@rickardp commented on Sat Nov 14 2015

@aluanhaddad Good points! Though I often find myself in a situation where this design is out of my control. Some code may be generated, or some tradeoffs might have been done for performance reasons (e.g. large data sets on mobile devices), and in any case that piece of code might not be maintained by me. IMHO one of the greatest strengths with C# is its ability to deal with real-world situations while still keeping your own code clean and maintainable.

Even as we are embracing the semantic difference between null and empty (e.g. where null means “not specified”), the sensible default behavior might still be to not traverse the collection when it is null in many (not all!) situations. After all, I suppose this is why the null-propagating operators were so much requested in the first place.


@aluanhaddad commented on Sat Nov 14 2015

While the ?. operator is wonderful, I worry that providing a syntactic sugar specifically for handling possibly null enumerables, will encourage people to return null instead of empty, and thus also encourage people to use the new null safe enumeration syntax everywhere.

I think that the combination of the ?. operator and #5032, if adopted in its current form, will effectively make nullability the safe and syntactically supported way to represent optional values. If we imagine a C# where values are (assumed to be) non-nullable by default, then nullability and the ?. operator effectively become C#’s Maybe/Option monad. However, while this makes sense for scalar values, I don’t think it makes sense to use it for optional aggregate values because we can think of a nullable type as a conceptual Option<T>. Then, if we think of Option<T> as essentially a trivial collection which contains either 0 or 1 elements, it suggests that aggregate values do not likely need to be wrapped further. You can implement Option<T> as a library, providing an extension method to wrap possible null values, and then write queries over the optionals, but I digress.

At any rate, your extension method

public static IEnumerable<T> EmptyIfNull(this IEnumerable<T> enumerable) {
   return enumerable ?? Enumerable.Empty<T>();
}

actually handles the uncertainty quite well without the need for additional syntax.


@yaakov-h commented on Sat Nov 21 2015

Considering how often something like this is needed, what’s the value of returning null? i.e., what’s the semantic difference between null (there is no collection of items) versus an empty enumerable (there is no items in the collection)? In what case would a function or property that returns both be valid?


@paulomorgado commented on Mon Nov 30 2015

@yaakov-h, the difference is the difference between and empty box (empty collection) and no box (null).

If you have no box, you can assume you have no items. But that’s a particular interpretation of what you having no box means. There might be a box but hasn’t been handed to you yet. You cannot tell the color of a box if you have no box. Nor its size/capacity. You can fill an empty box, but you can’t fill no box.


@NickCraver commented on Sun May 29 2016

The confusion here I see is for new devs hitting null reference exceptions here. It’s just not expected, they don’t know that .GetEnumerator() is called underneath and it’s a compiler implementation detail that they’re hitting which isn’t very obvious. I don’t want to allocate a new collection of X every time just to not throw, and the extension method can only be applied to generic collections, not those of older IEnumerator (non-generic) types.

In almost all null cases, I simply don’t want to loop if there’s nothing to loop over. Today, that’s a wrapper:

if (myCollection != null) 
{
    foreach (var i in myCollection) { }
}

It’d be nice to have a cleaner syntax for this all around, as we have tons of these if statements. I strongly disagree this is automatically evidence of a bad API design, it often happens completely inside a method and with serialization as noted above. On the serialization front: we use protocol buffers which makes no distinction between empty and null, so you get a null.

I think we can do something here to save a lot of wrapper code, though where the best place for a ? (or alternative) is, I’m not picky about. Eliminating an extra 3 lines of code around many foreach statements would be nice, though. To be fair, I don’t think this will help the new developer case much at all. They’re still going to write a foreach and get a null ref before figuring it out and learning alternative approaches. I can’t think of any new-syntax way to help, it still has to be discovered.


@gafter commented on Sun May 29 2016

I don’t want to allocate a new collection of X every time just to not throw, and the extension method can only be applied to generic collections, not those of older IEnumerator (non-generic) types.

It sounds like Enumerator.Empty<object>() is exactly what you need. It returns something that implements the non-generic older interface IEnumerator too, and it doesn’t allocate something on each call.


@paulomorgado commented on Sun May 29 2016

@gafter, I think @NickCraver is saying that the foreach statement should, instead of myCollection.GetEnumerator() it should be something functionally equivalent to myCollection == null ? Enumerator.Empty<TItem>() : myCollection.GetEnumerator().

But that would be a breaking change.


@NickCraver commented on Mon May 30 2016

@paulomorgado Oh no - I’m saying foreach? (or other syntax) should behave that way. I am in no way arguing for a breaking change - that simply won’t happen. Do I think foreach should have behaved this way? Yeah, probably…but that ship has sailed, we can’t change it now.


@HaloFour commented on Mon May 30 2016

public static class EnumerableExtensions {
    public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> enumerable) {
        return (enumerable != null) ? enumerable : Enumerable.Empty<T>();
    }
}

@paulomorgado commented on Mon May 30 2016

@NickCraver, that was my understanding, but didn’t want to open the can of worms of ? on statements. What’s next? while?? lock??

@HaloFour, I still operate under the premisse that extension methods should look and behave like instance methods.


@NickCraver commented on Mon May 30 2016

@paulomorgado none of those constructs suffer from this issue, nor does using, switch, etc. - I don’t buy the slippery slope argument here. I can’t think of even one other block this applies. This is directly and specifically a result of the compiler implementation of foreach calling .GetEnumerator() underneath and unexpectedly throwing a null reference. The argument is simply for more terse handling of such a common case.


@aluanhaddad commented on Mon May 30 2016

the extension method can only be applied to generic collections, not those of older IEnumerator (non-generic) types.

You can define extension methods for non generic types.

The confusion here I see is for new devs hitting null reference exceptions here. It’s just not expected, they don’t know that .GetEnumerator() is called underneath and it’s a compiler implementation detail that they’re hitting which isn’t very obvious.

I think the problem is that the error message is expressed in terms of the compiler implementation, not that there is an error. Imagine if the error message read “Unable to enumerate null”, wouldn’t that clear things up?

If methods ignore the nullness of the enumerables they receive, merging the concept of null with empty, they are likely to propagate null in their return values. I think that would be harmful. Everyone would use the hypothetical new nullsafe foreach everywhere.


@NickCraver commented on Mon May 30 2016

You can define extension methods for non generic types.

Yes, if we want to define hundreds of extension methods. I was specifically talking about the generic extension methods proposed earlier, the only reasonable thing that may be added in almost all cases.

I agree the error message isn’t obvious, and clearing it up would help, but it still doesn’t address the usability and verbosity issue of wrapping everything in if (enumerable != null) { } today. It has little to do with propagating null, you choose whether to do that today and you’d choose whether to do it with a new syntax. I don’t buy the argument of it being a bad thing because it more easily enables you to do what you were going to do anyway. By using the new syntax, intent is clear. The same way it’s clear (and explicitly opted-into) with ?. in C# 6.

I don’t believe this enables any better or worse behavior than today’s verbose method. It simply allows developers to do what they want with less syntax, exactly as ?. does already.

I think that would be harmful. Everyone would use the hypothetical new nullsafe foreach everywhere.

Two things here: 1. This assumes that it’s harmful. Some people prefer to return null. We certainly do at Stack Overflow, we don’t want the allocation of an empty thing just to do nothing with it. 2. That’s a huge assumption with no backing. People don’t use ?. everywhere either - not even close. I think this is a very bad assumption to base any decisions on.


@HaloFour commented on Mon May 30 2016

@paulomorgado

I still operate under the premisse that extension methods should look and behave like instance methods.

That’s your decision, but my code is perfectly legal. It’s pretty convenient to be able to invoke extension methods off null specifically to handle easy/fluent checks like that. Note that throwing NullReferenceException when trying to invoke an instance method on null is specifically a C# limitation as a part of the language, the CLR is perfectly happy to allow it via the call opcode.


@yaakov-h commented on Mon May 30 2016

Note that throwing NullReferenceException when trying to invoke an instance method on null is specifically a C# limitation

Please explain which IL opcodes the C# compiler emits that causes this.

My understanding is that NullReferenceException is the CLR’s reinterpretation of a low-address access violation, and is not part of C#.

On 31 May 2016, at 8:27 AM, HaloFour notifications@github.com wrote:

Note that throwing NullReferenceException when trying to invoke an instance method on null is specifically a C# limitation


@HaloFour commented on Mon May 30 2016

@yaakov-h

C# always uses callvirt when invoking instance methods, even if the method isn’t virtual. That opcode has the side effect of always throwing NullReferenceException if the instance is null, which satisfies C#’s language specification requirement:

https://blogs.msdn.microsoft.com/ericgu/2008/07/02/why-does-c-always-use-callvirt/

If C# were to instead use the call opcode for instance methods then the CLR would allow them to be called and the this pointer would be null. You’d lose virtual dispatch on virtual methods in those cases, though.


@aluanhaddad commented on Mon May 30 2016

@NickCraver First of all I did not mean to come off as dismissing the value of returning null from a method which returns a collection, if it means improved performance in a critical path, then that is a perfectly valid reason to use it. My point is that I do not want to see the convenience of this foreach? style construct encourage conflation of null with empty.

With regard to performance, I think it is valid but, as @gafter pointed out, methods that return System.Collections.IEnumerable can delegate to System.Linq.Enumerable.Empty<Object>, so there is no allocation penalty.

With regard to extension methods, I’d be curious to see how many collection types you would need to define an extension method for. Hundreds does sounds very painful, but that is a lot of very specific types to be returning, especially if they are mostly used with foreach. Again, I don’t know your use case.

That’s a huge assumption with no backing. People don’t use ?. everywhere either - not even close. I think this is a very bad assumption to base any decisions on.

Well, all of my evidence is anecdotal, and thus should be disregarded, but I know many programmers who advocate defensive programming at the point of use. In other words, they are not confident in the API contract or it is insufficiently specified. In fact, it’s been suggested to me that I should check IEnumerables for null even when returned by internal types which I initialize with Enumerable.Empty

Anyway, if your code base is full of

if(values != null) 
{
    foreach (var value in values) { ... }    
}

I would assume you want to replace them all with foreach? (or whatever syntax it would be). That would certainly mean propagating use of the new syntax. Additionally, as you bring up the learning curve for new programmers, they will now have to ask themselves, why are there 2 foreach constructs? Which one do I use? And I predict, again without evidence, that the answer would often be “the safe one”. Which is safe for some definition of safe. And it would likely be the best choice when working in a code base full of collection returning methods that propagate nulls.

Edit: fixed formatting.


@NickCraver commented on Mon May 30 2016

@aluanhaddad How do you see this as any different than ?.Max() or ?.Where(), etc.? All of these debates applied to the safe navigation (?.) operator, and the community saw benefit over any perceived downsides. Have we seen devs go crazy with that and use it everywhere? I certainly haven’t, on the contrary: from what I’ve seen it’s very rarely used and almost always where appropriate. In fact the use cases I’ve seen like deserialized structures are very much in line with the use cases in this issue.

Would I use foreach? in the current if case? Absolutely. It’s a shorter way to get the same effect. It’s the same as ?. instead of nested ifs, { get; set; } instead of a full property with a declared backer, etc. I don’t see this as perpetrating anything “wrong”. Everything it does exists today, we just have to write more code to do it. Many additions over the past few versions of C# are exactly that: new syntax or constructs to make common cases more terse.

As for IEnumerable, there are tons of types in the BCL that are IEnumerable and not a generic version. Each would need its own extension method. There’s a lot of old business code started before generics also follows this pattern of a specific collection type as well, but luckily I don’t have that problem anymore. I have at past jobs, though.

I think the “programmers will do X” argument is moot in either case. If the argument is “they’ll just use foreach?”, then wouldn’t that same group just be adding an if wrapper today? That’s exactly what I’d do. Why can’t we make life easier? That’s what all new language features aim to do.


@aluanhaddad commented on Mon May 30 2016

I don’t see this as perpetrating anything “wrong”. Everything it does exists today, we just have to write more code to do it.

@NickCraver I certainly did not mean to come off as accusatory. I apologize.

I do think in general that it’s a poor practice to return null for values of type IEnumerable, but there are certainly exceptions, and I do not mean to judge. What I would like to avoid however, is the introduction of a new foreach construct.


@NickCraver commented on Tue May 31 2016

For IEnumerable? Yes sure, it’s easy to make the argument for not being null and there are zero allocations ways to achieve this. However, very often our return types are List<T>, Dictionary<TKey,TValye>, etc. - not the base IEnumerable<T>. Do you consider null invalid in those cases? We’d certainly rather not new up a collection just to throw it away, especially inside the same assembly and not on any public API. The same applies to null lists from deserialization as discussed earlier.

Also what about types that aren’t returned at all? In razor views for example you’re rendering the output and we have to put these if constructs wrapping everywhere as well. I think the “null return” is a narrow view of the much wider range of use cases. All of these arguments against (and reasoning for) mirror ?., which the community and C# team approved and serves as a tremendous time and code saver today.

To be clear: I’m not advocating specifically for foreach?, I’ve seen foreach(var i in? myEnumerable) and foreach(var i in myEnumerable?) proposed as well. Or, something else. I’m not all all picky about the syntax; there are many ways to improve over the extra 3 lines we require today.


@markrendle commented on Tue May 31 2016

foreach (var i in myEnumerable?) would seem to fit very nicely with the semantics of the existing null-safe operator, since it is applied to the variable rather than a keyword.


@aluanhaddad commented on Tue May 31 2016

However, very often our return types are List<T>, Dictionary<TKey,TValye>, etc. - not the base IEnumerable<T>. Do you consider null invalid in those cases?

I generally return these types through interfaces like IReadOnlyList<T>. If you are doing that, you can return a static field like the one returned by Enumerable.Empty<T> for the extension method on that type. If the collections are exposed via mutable interfaces, then you will need to check for null regardless if you want to make use of that interface. However, if you are only reading from them, why not enjoy the benefits, like IReadOnlyList<T>’s covariance, and generally easier to reason about code, that you can get from an immutable interface?

@markrendle I do find that the syntax foreach (var i in myEnumerable?) makes this more palatable. It is acting on the value, not appearing to introduce a special null aware keyword.


@NickCraver commented on Tue May 31 2016

@aluanhaddad The “why?” for most of those is you’re making a lot of assumptions about a codebase based on personal experience, which we all do. We only know what we’ve seen. However, you must realize many people don’t use those interfaces, don’t want to cast as those interfaces, and all of that complicates code in other ways.

If the collections are exposed via mutable interfaces, then you will need to check for null regardless if you want to make use of that interface.

No…I wouldn’t. That’s the entire point. I want to say “if null, skip it”, that’s what this entire issue is about. Also don’t assume read-only behavior, that’s a bad assumption. Language features and constructs cannot make assumptions like this, they have to handle the widest variety of cases and throw warning or errors for all the rest.

In general most comments here ignore performance. They miss the point of not wanting to call .GetEnumerator() at all if there’s nothing there. Using an empty collection is a loss in performance. You’ll not convince me to use empty collections everywhere - that’s just not how we do things here, and many places I’ve been. It’s not the fastest code you can write, a null check is. The assumption of using empty collections everywhere also assumes you always control both the input and output of every method. This is very rarely the case everywhere.

Why not use IReadOnlyList<T>? Because now I’ve arbitrarily (and drastically) restricted the methods available down to satisfy some requirement that was arbitrarily imposed. It also totally rules out the read/write case, of which we have many. The answer here should not be “rewrite all of your perfectly valid code and create more allocations and restrictions”. We can do better. This issue is about doing better.


@ghost commented on Tue May 31 2016

in? coalesces the pretty syntax + user intent, and it’s more C#-y than the other proposed options.

Updated 25/03/2017 00:10

Higher Kinded Polymorphism / Generics on Generics

dotnet/csharplang

@diab0l commented on Thu Apr 23 2015

tl;dr

Haskell has monads Monads are like bacon C# needs bacon

Introduction

I have a mad craving for higher kinded polymorphism in C#. And I have no blog to call my own, so here’s an essay on this stuff.

That’s a fancy name with a lot of crazy type theory and papers behind it, but if you have an understanding of how generic types work in C#, the concept is not terribly hard to understand.

What C# with a taste of bacon would look like

public static T<A> To<T, A>(this IEnumerable<A> xs)
    where T : <>, new(), ICollection<> 
{
    var ta = new T<A>();
    foreach(var x in xs) {
        ta.Add(x);
    }
    return ta;
}

...
{
    var data = Enumerable.Range(0, 20);

    var set = data.To<HashSet<>, int>(); // sorcery!
    var linkedList = data.To<LinkedList<>, int>();
    var list = data.To<List<>, int>();
}

What is going on here?

where T : <>,           // 1
          new(),        // 2
          ICollection<> // 3
  1. T is constrained to be a generic type definition with one type parameter.
    • In CLR lingo: T is a generic type of arity 1
    • In type theory lingo: T is a type constructor of kind * -> *
  2. Also it should have a default constructor
  3. And it should implement ICollection<> (meaning for each type X, T<X> implements ICollection<X>)

Using this you could convert an IEnumerable<T> to any other type that is a collection. Even all the ones you have never thought about, including the weird ones from libraries which do not get a whole lot of support because nobody uses them (except of course you).

Like HashSet (such a weird collection) or LinkedList (you would need to be crazy). They are fine citizens of System.Collections.Generic and very useful, yet they don’t get the love they deserve, because they are not as famous as List<> and implementing To...() methods in Linq for all of them would be a painful task.

However, with higher kinded polymorphism, they could all get a general concise implementation.

Where’s the rest of that bacon?

That general conversion function is just the tip of the iceberg. You can do all kinds of crazy transformations with higher kinded polymorphism. And since it allows for such lovely abstractions you only have to implement them once.

Or better yet: Somebody else implements them in a NuGet package and you don’t need to care. Composition over coding.

Haskell? Is that a dog’s name?

That NuGet package could be called something neat and concise like, say, Prelude. Yes, what a fine name! There are some other party poopers, but the lack of Higher Kinded Polymorphism is the biggest road block in stealing all the juicy bacon from the Haskell community.

You know how Linq is awesome? Do you also know how Linq is an implementation of the List Monad? (kind of) Well, there are lots of more Monads in Prelude and most of them are awesome. And currently a bitch to implement in C#.

Plus, HKP would allow to abstract on the concept of Monads! And on concepts like Tuples (never heard of them), Functors (not what you’re thinking), Arrows, Categories and all the crazy math that comes with them.

I’ve put together a gist of how wonderful this would be in combination with some other features for implementing Maybe.

I don’t know what you’re talking about, but it sounds expensive

Let’s first look at a summary of the benefits that HKP would bring to C# 1. This feature would make C# the most relevant functional programming language with sub-typing and strong static type checking 2. A natural extension to the work done by the Linq team 3. A natural extension to generics 4. Much more natural porting of Haskell code (think about it: years upon years of research on bacon finally in a consumable form) 5. A real implementation of the Maybe monad (about time) 6. More expressiveness without sacrificing static typing 7. HKPs allow something kind of Meta-programming without the nonsense. Whoever used C++ before knows how easily template programming becomes a nightmare. On the other hand, Haskell programmers are delighted by their juicy type system. 8. Have I mentioned bacon?

Now let’s talk about work: - Before anything else, a proper implementation would require CLR support - That would be quite involved, but not impossible. Also I believe it can be implemented as a strict extension to the current metadata without breaking existing libraries - As a consequence, the F# crowd would benefit from this. I bet they are overjoyed to hear about bacon - As another consequence, implementing Haskell on top of .Net would be much less of a pain - C# Syntax - In C# we can already refer to generic type definitions in typeof() as in typeof(IDictionary<,>) - I think the where T : <,> clause seems neat, but is probably not powerful enough (no way to constrain variance on T’s parameters or ‘swap’ parameters for implementations) - maybe more like where T<,> : <U, X>, IDictionary<X, U> - or rather void Foo<A<B, C>, D>() where A<B, C> : IDictionary<C, B> where B : class - Well, the syntax needs work. - Type checking - it’s not work if it’s fun

But I’m a vegetarian

Think of Bacon as an abstract higher kinded type class with non-carnivorous implementations


@VSadov commented on Thu Apr 23 2015

There is an obvious issue with CLR not supporting higher-kinded types. Some languages (Scala, F*) seem to be able to get around such limitations of underlying runtimes, but I do not know how well that works in practice.

@MadsTorgersen if not already there, higher kinded generics may need to be added to the list of possible future directions. Perhaps next to the Meta-programming :-).


@diab0l commented on Fri Apr 24 2015

From what I’ve seen on UserVoice and SO, there’s encodings to do this stuff in F# using their inlining system.

But these encodings tend to be ugly, complex and compromising. That definitely doesn’t sound like something I want for C#.

It’s also worth noting that the feature request has been rejected for F#, since it would require CLR support, it’s costs outweigh it’s benefits, etc., however that was before Core was open sourced and all this crazy open development started


@GSPP commented on Wed Apr 29 2015

@diab0l can you give more examples for what this would be good for? I always wondered what practical things you can do with higher kinded types.

For C# 6 they are not going to touch the CLR but there are other potential changes queued up (e.g. structural types and default implementations for interface methods). Maybe C# 7 can batch all of them into a new incompatible runtime.


@isaacabraham commented on Sat May 02 2015

@diab0l I don’t think it’s been rejected from F# because of lack of CLR support - I believe it could be done in a type erased style - it’s simply not high up enough the feature list on uservoice.

I’ve also been hearing people in the F# community asking for GADTs first.


@diab0l commented on Sun May 03 2015

@isaacabraham Of course it could be implemented type-erased style, but that’s an unpleasant can of worms.

If it were implemented like C++ templates, it would be a source level feature, meaning you can’t have higher kinded polymorphic methods in assemblies. I think we can reach consensus that such a feature would only pollute the language.

If it were implemented like Java generics, it would lead to all sorts of nonsense. For example you couldn’t do typeof(M<>) inside the hkpm, since the type has been erased.

So to implement this feature in a reusable way, there would at least need to be a way for the C# compiler to 1) actually compile the hkpm to an assembly 2) encode the extra information about the type (via an attribute perhaps) 3) decode that extra information so the method from the assembly can actually be used 4) use some very clever IL hacks to make it “just work” for the implementing method and at the call site

Now since it has to happen at assembly level, that would essentially be a language-agnostic extension to the CLR’s common type system. And since the extra information would need to be encoded, it wouldn’t be type erased at all, it would be reified, albeit in an ugly hack.

If we are going to extend the CLR’s common type system with some cool feature anyway, then I would suggest we do it right: by adding it as a first-level feature to the standard and implementing it right instead of via (clever or not) ugly hacks.


@diab0l commented on Sun May 03 2015

@GSPP To be frank: I can’t give you a whole lot of examples. Until recently I just haven’t given it any thought.

However, what I can tell you is that, as an abstraction feature which abstracts over abstract data structures it would primarily allow us to write some neat libraries. Also, in Haskell it’s used quite natural as part of every day programming for everything, so it allows for a different style in coding.

The best example I can currently come up with is abstracting over the Linq Zoo. Consider you write a function which only relies on the shared semantics of Linq-to-Objects (IEnumerable<>), Database Linq (IQueryable<>), PLinq (IParallelEnumerable<>), Reactive extensions (IObservable<>), wherever IQobservable<> lives and whichever other crazy Linq-style APIs everybody whips up.

The only difference in the shared methods of these APIs (Select(), First(), …) is a) the data type they operate on (IEnumerable<>, IQueryable<>, …) and b) whether they straight up take Func<> or Expression<Func<>> as arguments.

We cannot currently abstract over a) or b) :(

Currently, as a library author who intends to write a method which works on either of these APIs, you would have to write your function each time for each API (without casting to IEnumerable<> which forces a query to lose it’s semantics, for example), even if your function does not care whether it queries an IEnumerable<> or an IParallelEnumerable<> or even an IQueryable<>.

With the introduction of HKPMs, and a retrofitted static interface ILinq<> for Linq implementations, you could write your awesome function once and it would work not only on these 5 Linq implementations, but on every future implementation as well.


@diab0l commented on Sun May 03 2015

Please do not understand me wrong. I am well aware that implementing this feature is going to be a big undertaking and not going to happen anytime soon, if at all. At least not until the CLR ports have become stable and established.

Also, it’s not clear whether higher kinded polymorphism would be a good fit for C#. Maybe there’s some better way to raise the bar on abstraction.

What I think is clear is that C# and the CLR have incorporated features from functional languages with great success and the trend for using C# as a functional language is strong.

Having all this in mind, I think it’s worthwhile to explore how C# would benefit from first-level support for Higher Kinded Polymorphism and what such a syntax would be like.

Also I think that, along with related issues it raises the question: Should the common type system as a one-size-fits-all solution be all that common?


@asd-and-Rizzo commented on Mon May 04 2015

There is the example for HKT in C# http://www.sparxeng.com/blog/software/an-example-of-what-higher-kinded-types-could-make-possible-in-c.


@MI3Guy commented on Mon May 11 2015

Another advantage would be the ability to use value type collections (e.g. ImmutableArray<T>) without boxing them or writing a method that uses that specific collection.


@DrPizza commented on Mon Jun 20 2016

Also, it’s not clear whether higher kinded polymorphism would be a good fit for C#.

Template template parameters are a good fit for C++, so it’s natural enough that generic generic parameters would be a good fit for C#. Being able to make Linq methods independent of concrete classes seems nice enough.


@gafter commented on Fri Sep 04 2015

@TonyValenti Please suggest that in a new issue.


@aluanhaddad commented on Wed Sep 16 2015

I would love to see this addition if some future version of the framework enables it.


@oscarvarto commented on Mon Jun 20 2016

+1 I am also craving for some bacon!


@mooman219 commented on Thu Jun 23 2016

+1 Ran into an issue where I needed this today


@aluanhaddad commented on Thu Jun 23 2016

It’s too bad this is one of those things that definitely is going to require CLR support. But then again maybe it’s a good opportunity for the CLR to evolve.


@Pauan commented on Fri Sep 23 2016

Please excuse the F#, but here is an example of where higher-kinded polymorphism would help out a lot.

There is a function called map which is used quite a lot in F#:

List.map : ('a -> 'b) -> list<'a> -> list<'b>
Array.map : ('a -> 'b) -> array<'a> -> array<'b>
Seq.map : ('a -> 'b) -> seq<'a> -> seq<'b>
Option.map : ('a -> 'b) -> option<'a> -> option<'b>
Event.map : ('a -> 'b) -> Event<'a> -> Event<'b>
Async.map : ('a -> 'b) -> Async<'a> -> Async<'b>

Its behavior is fairly simple. It allows you to take a “container” (like a list, array, dictionary, etc.) and transform every element inside of the container:

List.map (fun x -> x + 10) [1; 2; 3; 4]

The end result of the above code is [11; 12; 13; 14]. In other words, for every element in the list, we added 10 to it.

As you can see, map is used for many different types. It would be nice to be able to write functions that can work on any type as long as that type has a map function.

Because F# has interfaces (just like C#), you might try this:

type IMap<'T> = interface
  abstract member Map: ('a -> 'b) -> 'T<'a> -> 'T<'b>
end

// This is just for convenience: it is easier to use and auto-casts to the IMap interface
let map fn (a : IMap<'T>) =
  a.Map(fn, a)

And then you could implement the IMap interface on any class or discriminated union:

type Option<'a> =
  | None
  | Some of 'a

  interface IMap<Option> with
    member this.Map(fn, a) =
      match a with
      | None -> None
      | Some a -> Some (fn a)

You can then use the map function on anything which implements the IMap interface. And you can write generic code which uses the map function:

let mapadd a b =
  map (fun x -> x + b) a
// Examples of using it:
mapadd (Some 1) 5   // the end result is (Some 6)
mapadd [1; 2; 3] 5  // the end result is [6; 7; 8]

The mapadd function will work on any type which implements IMap. This is marvelous: without interfaces, we would need to write the mapadd function multiple times: once per type. In other words, we would need List.mapadd, Array.mapadd, Option.mapadd, Async.mapadd, etc.

But with interfaces, we can write it once and reuse it for many types! And of course static typing is fully preserved: you get a compile-time error if you make any mistakes, such as calling mapadd on a type which does not implement IMap.

The mapadd function is very simple, but this also works with more complex functions: you can write a complex function which works with anything which implements IMap, rather than needing to copy-paste the complex code for each type.

Unfortunately, this does not work, because .NET lacks higher-kinded polymorphism:

error FS0712: Type parameter cannot be used as type constructor

In other words, you cannot specify the type 'T<'a> where 'T is a type parameter (like in the IMap interface).

This also applies to other functions as well, like bind, filter, flatten, fold, iter, etc.

Quite a lot of the list and array functions would benefit from this. In fact, any “container” (list, seq, Async, Option, etc.) can benefit a lot from higher-kinded polymorphism. Of course there’s plenty of other examples where this is useful (monads, arrows, etc.) but those examples tend to be familiar only to functional programmers.

Unfortunately I do not know C# well enough to give any examples of where higher-ordered polymorphism would be useful in C#, but I hope that map is familiar enough that C# programmers can see how this would be useful.

So, in short: higher-kinded polymorphism is simply a more powerful form of generics. It is useful for precisely the same reason why generics and interfaces are useful: it allows us to write code which can be reused, rather than reimplemented over and over again.

P.S. If somebody with more C# experience than me could translate the above F# code into equivalent C# code, that may help others with understanding what higher-kinded polymorphism is, how to use it, and what it’s good for.


@orthoxerox commented on Fri Sep 23 2016

This repo demonstrates a quite interesting approach to typeclasses in c#: https://github.com/CaptainHayashi/roslyn


@Alxandr commented on Tue Sep 27 2016

Actually, both C# and F# has higher kinded polymorphism to an extent. It’s what allows computational expressions in F#, and LINQ in C# to work. For instance, when you in C# do

for item in list
select item + 2

this gets converted into something like

list.Select(item => item + 2)

or in F#

List.map (fun item -> item + 2) list

This is done through some compile-time constraints that we are unfortunately unable to extend within the language. Basically what we’re asking for is the ability to create interfaces like this:

interface ILinqable<TSelf<..>> {
  TSelf<T1> Select(Func<T1, T2> func);
}

class List<T> : ILinqable<List<..>> {
  // need to implement select
}

@orthoxerox commented on Tue Sep 27 2016

@Alxandr not really, LINQ query expressions are a purely syntactic convention.


@aluanhaddad commented on Tue Sep 27 2016

@orthoxerox yes they are but the result is higher kinded typing for a very limited subset of operations. Consider:

static class EnumerableExtensions
{
    public static List<R> Select<T, R>(this List<T> list, Func<T, R> selector) => 
        list.asEnumerable().Select(f).ToList();

    public static List<T> Where<T>(this List<T> list, Func<T, bool> predicate) =>
        list.asEnumerable().Where(predicate).ToList();

    public static HashSet<R> Select<T, R>(this HashSet<T> set, Func<T, R> selector) => 
        new HashSet<R>(set.asEnumerable().Select(f));

    public static HashSet<T> Where<T>(this HashSet<T> set, Func<T, bool> predicate) =>
        new HashSet<T>(set.asEnumerable().Select(f));
}

var numbers = new List<int> { 0, 1, 2, 3, 4 };

List<string> values = 
    from n in numbers
    where n % 2 == 0
    select $"{n} squared is {n * n}";

var distinctNumbers = new HashSet<int> { 0, 1, 2, 3, 4 };

HashSet<int> distinctSquares = 
    from n in distinctNumbers
    select n * n;

@aluanhaddad commented on Tue Sep 27 2016

The problem is that it has to implemented for every collection type in order to be transparent. In Scala operations like map and filter take an implicit parameter which is used as a factory to create new collections choosing the correct collection type based on the source.


@OzieGamma commented on Tue Sep 27 2016

@aluanhaddad

Indeed overloading lets you use functions as if it was higher-kinded polymorphism.

But you still have to write all those overloads. That’s what we’d like to avoid.


@isaacabraham commented on Tue Sep 27 2016

This isn’t even overloading. There is the ability to “hijack” the LINQ keywords if your types have method that have certain names and signatures - same as foreach really.

So in that way I suppose there’s some similarity but in my limited understanding of HKTs, it’s not the same - you don’t have the reuse that they give you.


@aluanhaddad commented on Tue Sep 27 2016

I am not suggesting equivalence. I am suggesting that it is possible to slightly abstract over the type that is itself parameterized by using LINQ method patterns. I was not proposing this as an alternative to higher kinded types as it clearly is not. If Rx is not hijacking LINQ keywords, I hardly think this is, but it is certainly surprising and I would avoid this pattern.


@Pauan commented on Tue Sep 27 2016

@Alxandr It’s true that LINQ/computation expressions allow you to use the same syntax on multiple different types, but it is a hardcoded syntax trick.

Here is an example in C# where LINQ will not help you:

http://www.sparxeng.com/blog/software/an-example-of-what-higher-kinded-types-could-make-possible-in-c

This is the reason why higher kinded types are useful. I know you’re already aware of this, I’m mentioning this for the sake of other people who think that LINQ is “good enough”.


It’s also possible to hackily add in support for overloaded functions in F# by abusing inline functions and statically resolved type parameters:

https://github.com/gmpl/FsControl

This is essentially using the same trick that LINQ is using: any type which happens to implement a static method with the right name and right type will work.

But unlike interfaces: - All of the functions need to be inline, including any functions which use inline functions (this can cause code bloat and long compilation times). - The method names can collide (you can’t define two different “interfaces” with the same method name). - This trick only works in F#, it doesn’t work in C#.

So we still need higher-kinded types.


@Alxandr commented on Wed Sep 28 2016

@Pauan I am very well aware of this. I just tried to make a really simple explanation explaining to people who do not know what we want. LINQ is as you said a hardcoded compiler trick. Inline in F# is a bit more of a flexible compiler trick. We would like the CLR to support higher kinded generics. Although, you could make higher-kinded a compiler-only feature it would be better if the CLR supports it.


@diab0l commented on Wed Sep 28 2016

I would like to add some more clarification, especially since what I originally wrote may not be clear enough for people unfamiliar with higher kinded types. So here’s some theory. Somebody correct me if I’m wrong.

Proper Types Proper types are those inhabited by values which are not types themselves. Examples are int, bool, string and any other value (struct) or reference type (class). Generic types closed over all their type arguments (such as List<int> or KeyValuePair<string, int>) are also proper types.

Kinds Kinds are a formalization for type-level functions. There’s * which reads as type, which is no coincidence, because all proper types are of kind *. There’s also the operator -> which allows us to create kinds like * -> * which is a type function taking a proper type as parameter and returning a proper type as result. (Examples: List<> and Set<>)

Such type functions are also called type constructors, since you give them some parameters and they ‘construct’ a type for you. In other words, applying the proper type int to the type constructor List<> yields the proper type List<int>.

Generic types So, * -> * is the kind of generic types with arity 1 (List<>, Set<>, etc.), * -> * -> * is the kind of generic types with arity 2 (Tuple<,>, KeyValuePair<,>, Dictionary<,>). and so on. These are things we can already express within C# and the CLR and we call them generic types.

To slightly complicate the picture, we also have generic methods which are in a sense function constructors. They are like type constructors, except they do not return a proper type, but instead a proper function.

Higher kinded types What we cannot express are higher-kinded types. An example would be (* -> *) -> * -> *, which is a type function taking a type constructor and a proper type as argument and returning a type. Here’s what the signature could look like in C#:

T<U> Foo<T<>, U>();

Another useful kind would be (* -> *) -> (* -> *) which could be used to have a general mapping from one type constructor to another. To make this meaningful, we would need to know something about the types constructors and the way to do that would be constraints. We can currently neither have a type argument which is a type constructor itself and even if we could, we couldn’t meaningfully constrain it.

There are other things we cannot express. For example you can’t have a variable of type Action<> or of type Func<,>, so you can have generic methods, but not generic lambda methods.

Tl;dr; To sum it up, today we can range over the U in T<U>. What I want is to be able to range over the T in a meaningful way (with constraints).


@Alxandr commented on Wed Sep 28 2016

While I (think) I perfectly understood all of that (I’ve done haskell), I think the * -> * and (* -> *) -> * annotation is confusing for people who are not used to functional programming languages. I remember starting in F# and reading int -> int -> int is confusing if you’re not used to it.

To translate the same into something akin to TypeScript (C# doesn’t really have a func annotation) it could look something like this:

List: (T: *) => List<T>
Dictionary: (Key: *, Value: *) => Dictionary<Key, Value>

whereas what we would like to express is

Mappable: (T: (* => *)) => Mappable<T<>>

Not sure about the syntax, but I do believe we might want to try to write things in a format thats more similar to what most C# devs are used to (at least while we’re in the roslyn repo).

Or if an interface would help:

interface IMappable<T<>, A> {
  T<B> Map<B>(Func<A, B> func);
}

class List<T> : IMappable<List<>, T> {
  List<B> IMappable.Map<B>(Func<A, B> func) {
    List<B> result = new List<B>(Count);
    int index = 0;
    foreach (T item in this) {
      result[index++] = func(item);
    }
  }
}

Syntax is obviously something that should be discussed, and I don’t know what works best, but personally I think figuring out how things should work on the CLR level first is probably the best idea. Also, I haven’t written C# in a while, so apologies if there are any glaring errors in my snippets :)


@diab0l commented on Thu Sep 29 2016

@Alxandr I do agree completely and gosh, I hope this stuff eventually makes it’s way into typescript.

The interface is probably the best analogy. There are also proposals for ‘static interfaces’ which would allow for similar abstractions.


@toburger commented on Wed Oct 12 2016

it seems that there’s a light at the end of the tunnel: https://www.youtube.com/watch?v=hK5GJoH4PlI


@gusty commented on Wed Oct 12 2016

@toburger That technique doesn’t cover Higher Order Kinds. It allows you to define ‘first-order-kind typeclasses’ like <code>Monoid</code> and generalize over numeric types, but in order to be able to represent functors, applicatives or monads you still need to do something at the CLR level.


@Opiumtm commented on Wed Oct 12 2016

Your example is perfectly possible using current C# syntax

        public static T ConvertTo<T, TItem>(this IEnumerable<TItem> src)
            where T : ICollection<TItem>, new()
        {
            var result = new T();
            foreach (var item in src)
            {
                result.Add(item);
            }
            return result;
        }

        public static void Test()
        {
            var data = Enumerable.Range(1, 10);
            var list = data.ConvertTo<List<int>, int>();
            var set = data.ConvertTo<HashSet<int>, int>();
        }

@sideeffffect commented on Wed Oct 12 2016

if you haven’t heard, there’s this for HKT in F#

https://github.com/palladin/Higher

now I’m wondering, that this should also work in C# of course, this is more like a hack/workaround, but until we have a proper implementation of HKT in the language(s) and/or CLR, this could aleviate some problems


@Opiumtm commented on Wed Oct 12 2016

And from mentioned above article.

Example:

static T<string> GetPurchaseLogs(
                   T<Person> people, 
                   T<Purchase> purchases)
                   where T<?> : LINQable<?>
{
    return from person in people
           from purchase in purchases
           where person.Id == purchase.PurchaserId
           select person.Name + " purchased " + purchase.ItemName;
}

Exact generic logic to example above:

static IEnumerable<TItem3> CombineCheck<TArg1, TArg2, TItem1, TItem2, TItem3>(TArg1 a, TArg2 b, Func<TItem1, TItem2, TItem3> combine, Func<TItem1, TItem2, bool> check)
    where TArg1 : IEnumerable<TItem1>
    where TArg2 : IEnumerable<TItem2>
{
    return from item1 in a
        from item2 in b
        where check(item1, item2)
        select combine(item1, item2);
}

So, T<?> seems to be just short-hand for existing type constraints that require to explicitly declare type arguments of TItem1, TItem2 item types and TArg1, TArg2 enumerables.

And LINQable<?> here isn’t possible and not a case of higher-order polymorphism because LINQ queries use structural typing (LINQable is every type which provide standard Where(), Select() and so on methods - it isn’t bound to exact interfaces, it use structural typing instead)

So, C# should officially support some forms of structural typing as it already support structural typing for awaitables and LINQ-ables and don’t support general-purpose structural typing


@gabomgp commented on Thu Nov 10 2016

@Opiumtm I think structural typing is a very big change for C#, maybe something similar to traits/type classes/protocols would be better. Traits in Rust are very similiar to extension methods, but think in interfaces than extends the behavior instead of methods.


@asd-and-Rizzo commented on Thu Nov 17 2016

I am not sure, but seems case like next could also get use of HKT.

Given next usage of CsvHelper:

        /// <summary>
        /// Gets the csv string for the given models.
        /// </summary>
        /// <param name="models">The data models.</param>
        /// <returns>The csv string.</returns>
        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "OK")]
        public static string ToCsvString<TEntity, TMap>(IEnumerable<TEntity> models) where TMap : CsvClassMap<TEntity>
        {
            using (var content = new MemoryStream())
            {
                var textWriter = new StreamWriter(content, Encoding.UTF8);
                var config = new CsvConfiguration();
                config.RegisterClassMap<TMap>();
                var writer = new CsvWriter(textWriter, config);
                writer.WriteHeader<TEntity>();
                models.ForEach(writer.WriteRecord);
                textWriter.Flush();
                content.Position = 0;
                return new StreamReader(content).ReadToEnd();
            }
        }

And call:

ToCsvString<MyEnitty,MyMap>(...)

With HKT is seems would be next:

public static string ToCsvString<TMap<TEntity>>(IEnumerable<TEntity> models) where TMap : CsvClassMap<TEntity>

With HKT we will get less code to type when method is called - only 1 name of class, instead of 2:

ToCsvString<MyMap>(...)

And I do not understand Microsoft CodeAnalysis(CA) errors I see - may be will have no reason for these given HKT in place:

Severity    Code    Description Project File    Line    Suppression State
Error   CA1004  Consider a design where 'CsvBuilder.ToCsvString<TEntity, TMap>(IEnumerable<TEntity>)' doesn't require explicit type parameter 'TMap' in any call to it. CsvBuilder.cs   10  Active

Does CA suggest to make HKT into C# for proper design?


@bondsbw commented on Wed Dec 14 2016

The following DateTimeCollection type appears to satisfy the requirements for T in the original example:

public class DateTimeCollection<U> : ICollection<U>
    where U : DateTime

But DateTimeCollection has a type parameter constraint, so it would need to fail when that constraint is not satisfied:

var data = Enumerable.Range(0, 20);
var dtCollection = data.To<DateTimeCollection<>, int>();  // int does not inherit DateTime

The primary location of the problem is in the return type:

public static T<A> ... // Should be an error here, cannot construct 'T' with parameter 'A'

Because there is no guarantee that A is allowed as a parameter of T. So that should be specified in the type constraints for T:

public static T<A> To<T, A>(this IEnumerable<A> xs)
    where T : <A>, new(), ICollection<> 

@bondsbw commented on Wed Dec 14 2016

Perhaps the type constraint for ICollection<> needs to be specified as well:

public static T<A> To<T, A>(this IEnumerable<A> xs)
    where T : <A>, new(), ICollection<A> 

Otherwise wouldn’t this line fail?

ta.Add(x);

@alexandru commented on Thu Feb 02 2017

@aluanhaddad OOP subtyping / overloading doesn’t help with the most useful operation of all, which is bind / flatMap (I think it’s called SelectMany in .NET) because in OOP you have co/contra-variance as a natural effect of subtyping + generics and function parameters are contra-variant, which means you’ll lose type info.

In practice this means you can’t describe such operations by means of inheritance (and please excuse the Scala syntax, I’m just a newbie in F#):

trait Monad[F[_]] {
  // ...
  def flatMap[A,B](source: F[A])(f: A => F[B]): F[B]
}

object FutureMonad extends Monad[Future] {
  def flatMap[A,B](source: Future[A])(f: A => Future[B]): Future[B] = ???
}

Well, in Scala you can describe flatMap with inheritance, but then you need another feature in the type-system, called F-bounded types. Scala can do that too, but this is another feature you don’t see in other OOP languages, since this also needs higher-kinded types to be useful, (see article with details):

trait MonadLike[+A, Self[+T] <: MonadLike[T, Self]] { self: Self[A] =>
  def flatMap[B](f: A => Self[B]): Self[B]
}

class Future[+A] extends MonadLike[A,Future] {
  def flatMap[B](f: A => Future[B]): Future[B] = ???
}

Looks ugly but it is very useful for sharing implementation while not downgrading to the super-type in all those operations.

Updated 27/03/2017 09:44 1 Comments

Declaration of ref/out parameters in lambdas without typename

dotnet/csharplang

@ViIvanov commented on Sat Feb 07 2015

Hello!

I have a little suggestion for C# language. Let us have delegate like this:

delegate T Parse<T>(string text);

and we want to create an instance:

Parse<int> parse = text => Int32.Parse(text);

All is OK. What about ref/out parameters in a delegate?

delegate bool TryParse<T>(string text, out T result);

when we want to create an instance…

TryParse<int> parse1 = (string text, out int result) => Int32.TryParse(text, out result);

…we shoud to specify types on parameters.

Why is this required? What about a syntax below:

TryParse<int> parse2 = (text, out result) => Int32.TryParse(text, out result);

?


@mikedn commented on Sat Feb 07 2015

In this particular case you don’t need to write any of the parameter stuff, it’s just:

TryParse<int> parse1 = Int32.TryParse;

@alanfo commented on Sun Feb 08 2015

This would be a worthwhile improvement to type inference, in my view.

As ref and out are full keywords, they can’t possibly be type names and so there appears no reason why the compiler won’t be able to infer the type from the delegate signature.


@paulomorgado commented on Sun Feb 08 2015

I’m not sure I understand what you are proposing.

Would you care to elaborate a bit more?


@ViIvanov commented on Mon Feb 09 2015

@paulomorgado Of course! Let us see a code below:

delegate T Parse<T>(string text);
delegate bool TryParse<T>(string text, out T result);

static void Main() {
  // We can create an instance of Parse<int> like this:
  Parse<int> parseHex1 = (string text) => Int32.Parse(text, NumberStyles.HexNumber);
  // or like this (and, I think, this way is more simple and more readable):
  Parse<int> parseHex2 = text => Int32.Parse(text, NumberStyles.HexNumber);

  // To create an instance of TryParse<int> delegate
  // we must explicitly specify a types of arguments in a lambda expression:
  TryParse<int> tryParseHex1 = (string text, out int result) => Int32.TryParse(text, NumberStyles.HexNumber, null, out result);

  // And we can not now use a sintax like this:
  TryParse<int> tryParseHex2 = (text, out result) => Int32.TryParse(text, NumberStyles.HexNumber, null, out result);
}

Why this is meaningful: 1. In some scenarios user can have a delegates with a few (three, four, …etc) parameters and when at least one of them has a ref or out modifier user must explicitly specify types of all “delegate parameters”. 2. Follows from previous - we can not use anonymous types as type-parameters in delegates with ref or out parameters.


@omariom commented on Mon Feb 09 2015

:+1:


@paulomorgado commented on Mon Feb 09 2015

I ink you are missing the fact that, although you can’t declare by reference type parameters in C#, when a parameter is expressed as of being of type ref T (or out T, which is the same for the CLR - just extra validation from the compiler), the type is, actually, &T, which is not the same as T.


@ViIvanov commented on Mon Feb 09 2015

@paulomorgado Excuse me, can you explain what do you mean? Why in you point of view

TryParse<int> tryParseHex1 = (string text, out int result) => Int32.TryParse(text, NumberStyles.HexNumber, null, out result);

is correct (it is valid C# code) and

TryParse<int> tryParseHex2 = (text, out result) => Int32.TryParse(text, NumberStyles.HexNumber, null, out result);

is not? In a both examples, types of arguments exactly the same. But, in the second line, it calculated by the compiler, not specified by user explicitly.


@paulomorgado commented on Mon Feb 09 2015

I was trying to understand your issue, and I think I got it: the compiler should be able to infer the types from usage when there are out parameters. Is that it?


@ViIvanov commented on Mon Feb 09 2015

@paulomorgado Exactly! I’m sorry for my bad and poor English.


@alrz commented on Thu Nov 19 2015

:+1:


@Thaina commented on Thu Jan 14 2016

+1

thanks


@asvishnyakov commented on Fri Jan 15 2016

:+1:

Updated 25/03/2017 00:09

Proposal: allow non-public operators

dotnet/csharplang

@jskeet commented on Fri Jan 08 2016

Currently, all operators have to be public. This can reduce readability of internal-only code where an operator would otherwise be natural. This proposal is to allow things like:

internal static Foo operator +(Foo foo, Bar bar)

Use-case: in Noda Time we have types of: - public struct Instant - public struct Offset - internal struct LocalInstant

We have operations for adding an Offset to an Instant to get a LocalInstant, and the reverse subtraction operation. These would idiomatically be implemented using operators, and were while LocalInstant was public (long before the first release). It’s annoying that they can’t be :(

(I don’t know whether this would require a CLR change or whether it could just be a C# language change…)

I suspect there isn’t much benefit in having other access modifiers beyond public and internal, but that’s probably best discussed after deciding whether or not even allowing internal is desirable.


@leppie commented on Fri Jan 08 2016

Nice suggestion :+1:

I cant see any issue with the CLR for this. Edit: The only mention is the naming rules for operators, and nothing else beyond that.

I can’t even think it would be hard to implement in the compiler.


@HaloFour commented on Fri Jan 08 2016

I’m curious as to the reason that non-public operators aren’t allowed. This restriction is explicitly stated in the C# spec, §10.10:

The following rules apply to all operator declarations: - An operator declaration must include both a public and a static modifier.


@AdamSpeight2008 commented on Fri Jan 08 2016

@HaloFour Me Too.


@ViIvanov commented on Mon Jan 11 2016

@HaloFour,l @AdamSpeight2008

May be, reason is next: moving code with with non-public operators used from one project to another can have an unexpected semantic.


@ViIvanov commented on Mon Jan 11 2016

May be, compiler should require, that visibility of operator is same as operand with lowest type visibility?

For example, we should not have an ability to create an internal operator for two public types, but can create an internal operator for public and internal types.


@alrz commented on Mon Jan 11 2016

@ViIvanov Can you give an example? I think that would be the issue with moving any code!


@AdamSpeight2008 commented on Mon Jan 11 2016

We could allow the visibility to be treated as a scoping clarifier. eg var baz = internal( foo + bar ); Which will use an internal implementation of the operator plus.


@svick commented on Mon Jan 11 2016

@AdamSpeight2008 To me, that sounds like a separate feature on top of this one and one that is not very useful.


@AdamSpeight2008 commented on Mon Jan 11 2016

@svick It would be useful as it would let state that you explicitly what the internal overload.

public static t0 operator +( t0 x, t0 y ) {..}
private static t0 operator +(t0 x, t0 y) {...}

@svick commented on Mon Jan 11 2016

internal overload? You can’t have two methods that differ only by their access modifier in C# or IL. I don’t see why would you want that and this issue is not about that.

I assumed it was about situations like:

public class A
{
    public static A operator +(A a, B b) { … }
}

public class B
{
    internal static A operator +(A a, B b) { … }
}

But that still doesn’t seem very useful to me.

Updated 25/03/2017 00:08

Fork me on GitHub